]> git.gag.com Git - fw/sdcc/blob - src/pic16/gen.c
* src/pic16/ralloc.c (packRegsForAccUse): disabled functions with #if to eliminate...
[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
180   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
181                        line_no,
182                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
183                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
184                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
185                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
186                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
187                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
188                        ((result) ? AOP_SIZE(result) : 0));
189
190 }
191
192 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
193 {
194
195   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
196                        line_no,
197                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
198                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
199                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
200                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
201                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
202                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
203
204 }
205
206 void pic16_emitpcomment (char *fmt, ...)
207 {
208     va_list ap;
209     char lb[INITIAL_INLINEASM];  
210     char *lbp = lb;
211
212     va_start(ap,fmt);   
213
214     lb[0] = ';';
215     vsprintf(lb+1,fmt,ap);
216
217     while (isspace(*lbp)) lbp++;
218
219     if (lbp && *lbp) 
220         lineCurr = (lineCurr ?
221                     connectLine(lineCurr,newLineNode(lb)) :
222                     (lineHead = newLineNode(lb)));
223     lineCurr->isInline = _G.inLine;
224     lineCurr->isDebug  = _G.debugLine;
225
226     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
227     va_end(ap);
228
229 //      fprintf(stderr, "%s\n", lb);
230 }
231
232 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
233 {
234     va_list ap;
235     char lb[INITIAL_INLINEASM];  
236     char *lbp = lb;
237
238     if(!pic16_debug_verbose)
239       return;
240
241     va_start(ap,fmt);   
242
243     if (inst && *inst) {
244         if (fmt && *fmt)
245             sprintf(lb,"%s\t",inst);
246         else
247             sprintf(lb,"%s",inst);
248         vsprintf(lb+(strlen(lb)),fmt,ap);
249     }  else
250         vsprintf(lb,fmt,ap);
251
252     while (isspace(*lbp)) lbp++;
253
254     if (lbp && *lbp) 
255         lineCurr = (lineCurr ?
256                     connectLine(lineCurr,newLineNode(lb)) :
257                     (lineHead = newLineNode(lb)));
258     lineCurr->isInline = _G.inLine;
259     lineCurr->isDebug  = _G.debugLine;
260
261     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
262     va_end(ap);
263
264 //      fprintf(stderr, "%s\n", lb);
265 }
266
267 void pic16_emitpLabel(int key)
268 {
269   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
270 }
271
272 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
273 {
274
275   if(pcop)
276     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
277   else
278     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
279     
280 //    fprintf(stderr, "%s\n", pcop->name);
281 }
282
283 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
284 {
285
286   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
287
288 }
289
290
291 #if 1
292 #define pic16_emitcode  DEBUGpic16_emitcode
293 #else
294 /*-----------------------------------------------------------------*/
295 /* pic16_emitcode - writes the code into a file : for now it is simple    */
296 /*-----------------------------------------------------------------*/
297 void pic16_emitcode (char *inst,char *fmt, ...)
298 {
299     va_list ap;
300     char lb[INITIAL_INLINEASM];  
301     char *lbp = lb;
302
303     va_start(ap,fmt);   
304
305     if (inst && *inst) {
306         if (fmt && *fmt)
307             sprintf(lb,"%s\t",inst);
308         else
309             sprintf(lb,"%s",inst);
310         vsprintf(lb+(strlen(lb)),fmt,ap);
311     }  else
312         vsprintf(lb,fmt,ap);
313
314     while (isspace(*lbp)) lbp++;
315
316     if (lbp && *lbp) 
317         lineCurr = (lineCurr ?
318                     connectLine(lineCurr,newLineNode(lb)) :
319                     (lineHead = newLineNode(lb)));
320     lineCurr->isInline = _G.inLine;
321     lineCurr->isDebug  = _G.debugLine;
322
323 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
324
325 //    if(pic16_debug_verbose)
326 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
327
328     va_end(ap);
329 }
330 #endif
331
332
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
335 /*-----------------------------------------------------------------*/
336 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
337 {
338     bool r0iu = FALSE , r1iu = FALSE;
339     bool r0ou = FALSE , r1ou = FALSE;
340
341         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
342
343     /* the logic: if r0 & r1 used in the instruction
344     then we are in trouble otherwise */
345
346     /* first check if r0 & r1 are used by this
347     instruction, in which case we are in trouble */
348     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
349         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
350     {
351         goto endOfWorld;      
352     }
353
354     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
355     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
356
357     /* if no usage of r0 then return it */
358     if (!r0iu && !r0ou) {
359         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
360         (*aopp)->type = AOP_R0;
361         
362         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
363     }
364
365     /* if no usage of r1 then return it */
366     if (!r1iu && !r1ou) {
367         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
368         (*aopp)->type = AOP_R1;
369
370         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
371     }    
372
373     /* now we know they both have usage */
374     /* if r0 not used in this instruction */
375     if (!r0iu) {
376         /* push it if not already pushed */
377         if (!_G.r0Pushed) {
378           //pic16_emitcode ("push","%s",
379           //          pic16_regWithIdx(R0_IDX)->dname);
380             _G.r0Pushed++ ;
381         }
382         
383         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
384         (*aopp)->type = AOP_R0;
385
386         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
387     }
388
389     /* if r1 not used then */
390
391     if (!r1iu) {
392         /* push it if not already pushed */
393         if (!_G.r1Pushed) {
394           //pic16_emitcode ("push","%s",
395           //          pic16_regWithIdx(R1_IDX)->dname);
396             _G.r1Pushed++ ;
397         }
398         
399         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
400         (*aopp)->type = AOP_R1;
401         return pic16_regWithIdx(R1_IDX);
402     }
403
404 endOfWorld :
405     /* I said end of world but not quite end of world yet */
406     /* if this is a result then we can push it on the stack*/
407     if (result) {
408         (*aopp)->type = AOP_STK;    
409         return NULL;
410     }
411
412     /* other wise this is true end of the world */
413     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
414            "getFreePtr should never reach here");
415     exit(0);
416 }
417
418 /*-----------------------------------------------------------------*/
419 /* newAsmop - creates a new asmOp                                  */
420 /*-----------------------------------------------------------------*/
421 static asmop *newAsmop (short type)
422 {
423     asmop *aop;
424
425     aop = Safe_calloc(1,sizeof(asmop));
426     aop->type = type;
427     return aop;
428 }
429
430 static void genSetDPTR(int n)
431 {
432     if (!n)
433     {
434         pic16_emitcode(";", "Select standard DPTR");
435         pic16_emitcode("mov", "dps, #0x00");
436     }
437     else
438     {
439         pic16_emitcode(";", "Select alternate DPTR");
440         pic16_emitcode("mov", "dps, #0x01");
441     }
442 }
443
444 /*-----------------------------------------------------------------*/
445 /* resolveIfx - converts an iCode ifx into a form more useful for  */
446 /*              generating code                                    */
447 /*-----------------------------------------------------------------*/
448 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
449 {
450   if(!resIfx) 
451     return;
452
453   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
454
455   resIfx->condition = 1;    /* assume that the ifx is true */
456   resIfx->generated = 0;    /* indicate that the ifx has not been used */
457
458   if(!ifx) {
459     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
460 /*
461     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
462                         __FUNCTION__,__LINE__,resIfx->lbl->key);
463 */
464   } else {
465     if(IC_TRUE(ifx)) {
466       resIfx->lbl = IC_TRUE(ifx);
467     } else {
468       resIfx->lbl = IC_FALSE(ifx);
469       resIfx->condition = 0;
470     }
471 /*
472     if(IC_TRUE(ifx)) 
473       DEBUGpic16_emitcode("; ***","ifx true is non-null");
474     if(IC_FALSE(ifx)) 
475       DEBUGpic16_emitcode("; ***","ifx false is non-null");
476 */
477   }
478
479   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
480
481 }
482 #if 0
483 /*-----------------------------------------------------------------*/
484 /* pointerCode - returns the code for a pointer type               */
485 /*-----------------------------------------------------------------*/
486 static int pointerCode (sym_link *etype)
487 {
488
489     return PTR_TYPE(SPEC_OCLS(etype));
490
491 }
492 #endif
493 /*-----------------------------------------------------------------*/
494 /* aopForSym - for a true symbol                                   */
495 /*-----------------------------------------------------------------*/
496 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
497 {
498     asmop *aop;
499     memmap *space= SPEC_OCLS(sym->etype);
500
501     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
502     /* if already has one */
503     if (sym->aop) {
504             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
505         return sym->aop;
506     }
507
508     /* assign depending on the storage class */
509     /* if it is on the stack or indirectly addressable */
510     /* space we need to assign either r0 or r1 to it   */    
511     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
512
513         DEBUGpic16_emitcode("; ***", "sum->onStack || sym->iaccess");
514         
515         sym->aop = aop = newAsmop(0);
516         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
517         aop->size = getSize(sym->type);
518
519         /* now assign the address of the variable to 
520         the pointer register */
521         if (aop->type != AOP_STK) {
522
523             if (sym->onStack) {
524                     if ( _G.accInUse )
525                         pic16_emitcode("push","acc");
526
527                     pic16_emitcode("mov","a,_bp");
528                     pic16_emitcode("add","a,#0x%02x",
529                              ((sym->stack < 0) ?
530                               ((char)(sym->stack - _G.nRegsSaved )) :
531                               ((char)sym->stack)) & 0xff);
532                     pic16_emitcode("mov","%s,a",
533                              aop->aopu.aop_ptr->name);
534
535                     if ( _G.accInUse )
536                         pic16_emitcode("pop","acc");
537             } else
538                 pic16_emitcode("mov","%s,#%s",
539                          aop->aopu.aop_ptr->name,
540                          sym->rname);
541             aop->paged = space->paged;
542         } else
543             aop->aopu.aop_stk = sym->stack;
544         return aop;
545     }
546     
547     if (sym->onStack && options.stack10bit)
548     {
549         /* It's on the 10 bit stack, which is located in
550          * far data space.
551          */
552          
553       //DEBUGpic16_emitcode(";","%d",__LINE__);
554
555         if ( _G.accInUse )
556                 pic16_emitcode("push","acc");
557
558         pic16_emitcode("mov","a,_bp");
559         pic16_emitcode("add","a,#0x%02x",
560                  ((sym->stack < 0) ?
561                    ((char)(sym->stack - _G.nRegsSaved )) :
562                    ((char)sym->stack)) & 0xff);
563         
564         genSetDPTR(1);
565         pic16_emitcode ("mov","dpx1,#0x40");
566         pic16_emitcode ("mov","dph1,#0x00");
567         pic16_emitcode ("mov","dpl1, a");
568         genSetDPTR(0);
569         
570         if ( _G.accInUse )
571             pic16_emitcode("pop","acc");
572             
573         sym->aop = aop = newAsmop(AOP_DPTR2);
574         aop->size = getSize(sym->type); 
575         return aop;
576     }
577
578     //DEBUGpic16_emitcode(";","%d",__LINE__);
579     /* if in bit space */
580     if (IN_BITSPACE(space)) {
581         sym->aop = aop = newAsmop (AOP_CRY);
582         aop->aopu.aop_dir = sym->rname ;
583         aop->size = getSize(sym->type);
584         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
585         return aop;
586     }
587     /* if it is in direct space */
588     if (IN_DIRSPACE(space)) {
589         sym->aop = aop = newAsmop (AOP_DIR);
590         aop->aopu.aop_dir = sym->rname ;
591         aop->size = getSize(sym->type);
592         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
593         pic16_allocDirReg( IC_LEFT(ic) );
594         return aop;
595     }
596
597     /* special case for a function */
598     if (IS_FUNC(sym->type)) {   
599         sym->aop = aop = newAsmop(AOP_IMMD);    
600         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
601         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
602         strcpy(aop->aopu.aop_immd,sym->rname);
603         aop->size = FPTRSIZE; 
604         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
605         return aop;
606     }
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), 0);
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         pic16_allocDirReg (IC_LEFT(ic));
628
629         if(IN_DIRSPACE( space ))
630                 aop->size = PTRSIZE;
631         else if(IN_CODESPACE( space ))
632                 aop->size = FPTRSIZE;
633         else aop->size = AOP_SIZE( IC_LEFT(ic) );
634
635     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
636
637     /* if it is in code space */
638     if (IN_CODESPACE(space))
639         aop->code = 1;
640
641     return aop;     
642 }
643
644 /*-----------------------------------------------------------------*/
645 /* aopForRemat - rematerialzes an object                           */
646 /*-----------------------------------------------------------------*/
647 static asmop *aopForRemat (operand *op) // x symbol *sym)
648 {
649   symbol *sym = OP_SYMBOL(op);
650   iCode *ic = NULL, *oldic;
651   asmop *aop = newAsmop(AOP_PCODE);
652   int val = 0;
653   int offset = 0;
654   int viaimmd=0;
655
656
657         ic = sym->rematiCode;
658
659         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
660         
661         if(IS_OP_POINTER(op)) {
662                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
663         }
664
665         for (;;) {
666                 oldic = ic;
667
668 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
669         
670                 if (ic->op == '+') {
671                         val += (int) operandLitValue(IC_RIGHT(ic));
672                 } else if (ic->op == '-') {
673                         val -= (int) operandLitValue(IC_RIGHT(ic));
674                 } else
675                         break;
676                 
677                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
678         }
679
680         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
681
682         if(!op->isaddr)viaimmd++; else viaimmd=0;
683                 
684 /* set the following if to 1 to revert to good old immediate code */
685         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
686                 || viaimmd) {
687
688                 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
689
690                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
691
692 #if 0
693                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
694 #else
695                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
696 #endif
697
698                 PCOI(aop->aopu.pcop)->index = val;
699         } else {
700                 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
701
702                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
703 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
704         }
705
706
707         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
708                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
709 #if 0
710                 val, IS_PTR_CONST(operandType(op)));
711 #else
712                 val, IS_CODEPTR(operandType(op)));
713 #endif
714
715 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
716
717         pic16_allocDirReg (IC_LEFT(ic));
718
719         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
720                 aop->code = 1;
721
722   return aop;        
723 }
724
725 static int aopIdx (asmop *aop, int offset)
726 {
727   if(!aop)
728     return -1;
729
730   if(aop->type !=  AOP_REG)
731     return -2;
732         
733   return aop->aopu.aop_reg[offset]->rIdx;
734
735 }
736 /*-----------------------------------------------------------------*/
737 /* regsInCommon - two operands have some registers in common       */
738 /*-----------------------------------------------------------------*/
739 static bool regsInCommon (operand *op1, operand *op2)
740 {
741     symbol *sym1, *sym2;
742     int i;
743
744     /* if they have registers in common */
745     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
746         return FALSE ;
747
748     sym1 = OP_SYMBOL(op1);
749     sym2 = OP_SYMBOL(op2);
750
751     if (sym1->nRegs == 0 || sym2->nRegs == 0)
752         return FALSE ;
753
754     for (i = 0 ; i < sym1->nRegs ; i++) {
755         int j;
756         if (!sym1->regs[i])
757             continue ;
758
759         for (j = 0 ; j < sym2->nRegs ;j++ ) {
760             if (!sym2->regs[j])
761                 continue ;
762
763             if (sym2->regs[j] == sym1->regs[i])
764                 return TRUE ;
765         }
766     }
767
768     return FALSE ;
769 }
770
771 /*-----------------------------------------------------------------*/
772 /* operandsEqu - equivalent                                        */
773 /*-----------------------------------------------------------------*/
774 static bool operandsEqu ( operand *op1, operand *op2)
775 {
776     symbol *sym1, *sym2;
777
778     /* if they not symbols */
779     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
780         return FALSE;
781
782     sym1 = OP_SYMBOL(op1);
783     sym2 = OP_SYMBOL(op2);
784
785     /* if both are itemps & one is spilt
786        and the other is not then false */
787     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
788         sym1->isspilt != sym2->isspilt )
789         return FALSE ;
790
791     /* if they are the same */
792     if (sym1 == sym2)
793         return TRUE ;
794
795     if (strcmp(sym1->rname,sym2->rname) == 0)
796         return TRUE;
797
798
799     /* if left is a tmp & right is not */
800     if (IS_ITEMP(op1)  && 
801         !IS_ITEMP(op2) &&
802         sym1->isspilt  &&
803         (sym1->usl.spillLoc == sym2))
804         return TRUE;
805
806     if (IS_ITEMP(op2)  && 
807         !IS_ITEMP(op1) &&
808         sym2->isspilt  &&
809         sym1->level > 0 &&
810         (sym2->usl.spillLoc == sym1))
811         return TRUE ;
812
813     return FALSE ;
814 }
815
816 /*-----------------------------------------------------------------*/
817 /* pic16_sameRegs - two asmops have the same registers                   */
818 /*-----------------------------------------------------------------*/
819 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
820 {
821     int i;
822
823     if (aop1 == aop2)
824         return TRUE ;
825
826     if (aop1->type != AOP_REG ||
827         aop2->type != AOP_REG )
828         return FALSE ;
829
830     if (aop1->size != aop2->size )
831         return FALSE ;
832
833     for (i = 0 ; i < aop1->size ; i++ )
834         if (aop1->aopu.aop_reg[i] !=
835             aop2->aopu.aop_reg[i] )
836             return FALSE ;
837
838     return TRUE ;
839 }
840
841 /*-----------------------------------------------------------------*/
842 /* pic16_aopOp - allocates an asmop for an operand  :                    */
843 /*-----------------------------------------------------------------*/
844 void pic16_aopOp (operand *op, iCode *ic, bool result)
845 {
846     asmop *aop;
847     symbol *sym;
848     int i;
849
850     if (!op)
851         return ;
852
853 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
854
855     /* if this a literal */
856     if (IS_OP_LITERAL(op)) {
857         op->aop = aop = newAsmop(AOP_LIT);
858         aop->aopu.aop_lit = op->operand.valOperand;
859         aop->size = getSize(operandType(op));
860         return;
861     }
862
863     {
864       sym_link *type = operandType(op);
865 #if 0
866       if(IS_PTR_CONST(type))
867 #else
868       if(IS_CODEPTR(type))
869 #endif
870         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
871     }
872
873     /* if already has a asmop then continue */
874     if (op->aop)
875         return ;
876
877     /* if the underlying symbol has a aop */
878     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
879       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
880         op->aop = OP_SYMBOL(op)->aop;
881         return;
882     }
883
884     /* if this is a true symbol */
885     if (IS_TRUE_SYMOP(op)) {    
886         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
887       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
888       return ;
889     }
890
891     /* this is a temporary : this has
892     only four choices :
893     a) register
894     b) spillocation
895     c) rematerialize 
896     d) conditional   
897     e) can be a return use only */
898
899     sym = OP_SYMBOL(op);
900
901         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
902     /* if the type is a conditional */
903     if (sym->regType == REG_CND) {
904         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
905         aop->size = 0;
906         return;
907     }
908
909     /* if it is spilt then two situations
910     a) is rematerialize 
911     b) has a spill location */
912     if (sym->isspilt || sym->nRegs == 0) {
913
914       DEBUGpic16_emitcode(";","%d",__LINE__);
915         /* rematerialize it NOW */
916         if (sym->remat) {
917
918             sym->aop = op->aop = aop =
919                                       aopForRemat (op);
920             aop->size = getSize(sym->type);
921             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
922             return;
923         }
924
925 #if 1
926         if (sym->accuse) {
927             int i;
928             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
929             aop->size = getSize(sym->type);
930             for ( i = 0 ; i < 1 ; i++ ) {
931                 aop->aopu.aop_str[i] = accUse[i];
932 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
933             }
934             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
935             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
936             return;  
937         }
938 #endif
939
940 #if 1
941         if (sym->ruonly ) {
942           /*
943           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
944           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
945           //pic16_allocDirReg (IC_LEFT(ic));
946           aop->size = getSize(sym->type);
947           */
948
949           unsigned i;
950
951           aop = op->aop = sym->aop = newAsmop(AOP_STR);
952           aop->size = getSize(sym->type);
953           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
954             aop->aopu.aop_str[i] = fReturn[i];
955
956           DEBUGpic16_emitcode(";","%d",__LINE__);
957           return;
958         }
959 #endif
960         /* else spill location  */
961         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
962             /* force a new aop if sizes differ */
963             sym->usl.spillLoc->aop = NULL;
964         }
965         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
966                             __FUNCTION__,__LINE__,
967                             sym->usl.spillLoc->rname,
968                             sym->rname, sym->usl.spillLoc->offset);
969
970         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
971         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
972         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
973                                           getSize(sym->type), 
974                                           sym->usl.spillLoc->offset);
975         aop->size = getSize(sym->type);
976
977         return;
978     }
979
980     {
981       sym_link *type = operandType(op);
982 #if 0
983       if(IS_PTR_CONST(type)) 
984 #else
985       if(IS_CODEPTR(type)) 
986 #endif
987         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
988     }
989
990     /* must be in a register */
991     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
992     sym->aop = op->aop = aop = newAsmop(AOP_REG);
993     aop->size = sym->nRegs;
994     for ( i = 0 ; i < sym->nRegs ;i++)
995         aop->aopu.aop_reg[i] = sym->regs[i];
996 }
997
998 /*-----------------------------------------------------------------*/
999 /* pic16_freeAsmop - free up the asmop given to an operand               */
1000 /*----------------------------------------------------------------*/
1001 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1002 {   
1003     asmop *aop ;
1004
1005     if (!op)
1006         aop = aaop;
1007     else 
1008         aop = op->aop;
1009
1010     if (!aop)
1011         return ;
1012
1013     if (aop->freed)
1014         goto dealloc; 
1015
1016     aop->freed = 1;
1017
1018     /* depending on the asmop type only three cases need work AOP_RO
1019        , AOP_R1 && AOP_STK */
1020 #if 0
1021     switch (aop->type) {
1022         case AOP_R0 :
1023             if (_G.r0Pushed ) {
1024                 if (pop) {
1025                     pic16_emitcode ("pop","ar0");     
1026                     _G.r0Pushed--;
1027                 }
1028             }
1029             bitVectUnSetBit(ic->rUsed,R0_IDX);
1030             break;
1031
1032         case AOP_R1 :
1033             if (_G.r1Pushed ) {
1034                 if (pop) {
1035                     pic16_emitcode ("pop","ar1");
1036                     _G.r1Pushed--;
1037                 }
1038             }
1039             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1040             break;
1041
1042         case AOP_STK :
1043         {
1044             int sz = aop->size;    
1045             int stk = aop->aopu.aop_stk + aop->size;
1046             bitVectUnSetBit(ic->rUsed,R0_IDX);
1047             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1048
1049             getFreePtr(ic,&aop,FALSE);
1050             
1051             if (options.stack10bit)
1052             {
1053                 /* I'm not sure what to do here yet... */
1054                 /* #STUB */
1055                 fprintf(stderr, 
1056                         "*** Warning: probably generating bad code for "
1057                         "10 bit stack mode.\n");
1058             }
1059             
1060             if (stk) {
1061                 pic16_emitcode ("mov","a,_bp");
1062                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1063                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1064             } else {
1065                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1066             }
1067
1068             while (sz--) {
1069                 pic16_emitcode("pop","acc");
1070                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1071                 if (!sz) break;
1072                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1073             }
1074             op->aop = aop;
1075             pic16_freeAsmop(op,NULL,ic,TRUE);
1076             if (_G.r0Pushed) {
1077                 pic16_emitcode("pop","ar0");
1078                 _G.r0Pushed--;
1079             }
1080
1081             if (_G.r1Pushed) {
1082                 pic16_emitcode("pop","ar1");
1083                 _G.r1Pushed--;
1084             }       
1085         }
1086     }
1087 #endif
1088
1089 dealloc:
1090     /* all other cases just dealloc */
1091     if (op ) {
1092         op->aop = NULL;
1093         if (IS_SYMOP(op)) {
1094             OP_SYMBOL(op)->aop = NULL;    
1095             /* if the symbol has a spill */
1096             if (SPIL_LOC(op))
1097                 SPIL_LOC(op)->aop = NULL;
1098         }
1099     }
1100 }
1101
1102 /*-----------------------------------------------------------------*/
1103 /* pic16_aopGet - for fetching value of the aop                          */
1104 /*-----------------------------------------------------------------*/
1105 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1106 {
1107     char *s = buffer ;
1108     char *rs;
1109
1110     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1111     /* offset is greater than
1112     size then zero */
1113     if (offset > (aop->size - 1) &&
1114         aop->type != AOP_LIT)
1115         return zero;
1116
1117     /* depending on type */
1118     switch (aop->type) {
1119         
1120     case AOP_R0:
1121     case AOP_R1:
1122         DEBUGpic16_emitcode(";","%d",__LINE__);
1123         /* if we need to increment it */       
1124         while (offset > aop->coff) {        
1125             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1126             aop->coff++;
1127         }
1128         
1129         while (offset < aop->coff) {
1130             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1131             aop->coff--;
1132         }
1133         
1134         aop->coff = offset ;
1135         if (aop->paged) {
1136             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1137             return (dname ? "acc" : "a");
1138         }       
1139         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1140         rs = Safe_calloc(1,strlen(s)+1);
1141         strcpy(rs,s);   
1142         return rs;
1143         
1144     case AOP_DPTR:
1145     case AOP_DPTR2:
1146         DEBUGpic16_emitcode(";","%d",__LINE__);
1147     if (aop->type == AOP_DPTR2)
1148     {
1149         genSetDPTR(1);
1150     }
1151     
1152         while (offset > aop->coff) {
1153             pic16_emitcode ("inc","dptr");
1154             aop->coff++;
1155         }
1156         
1157         while (offset < aop->coff) {        
1158             pic16_emitcode("lcall","__decdptr");
1159             aop->coff--;
1160         }
1161         
1162         aop->coff = offset;
1163         if (aop->code) {
1164             pic16_emitcode("clr","a");
1165             pic16_emitcode("movc","a,@a+dptr");
1166         }
1167     else {
1168             pic16_emitcode("movx","a,@dptr");
1169     }
1170             
1171     if (aop->type == AOP_DPTR2)
1172     {
1173         genSetDPTR(0);
1174     }
1175             
1176     return (dname ? "acc" : "a");
1177         
1178         
1179     case AOP_IMMD:
1180         if (bit16) 
1181             sprintf (s,"%s",aop->aopu.aop_immd);
1182         else
1183             if (offset) 
1184                 sprintf(s,"(%s >> %d)",
1185                         aop->aopu.aop_immd,
1186                         offset*8);
1187             else
1188                 sprintf(s,"%s",
1189                         aop->aopu.aop_immd);
1190         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1191         rs = Safe_calloc(1,strlen(s)+1);
1192         strcpy(rs,s);   
1193         return rs;
1194         
1195     case AOP_DIR:
1196       if (offset) {
1197         sprintf(s,"(%s + %d)",
1198                 aop->aopu.aop_dir,
1199                 offset);
1200         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1201       } else
1202             sprintf(s,"%s",aop->aopu.aop_dir);
1203         rs = Safe_calloc(1,strlen(s)+1);
1204         strcpy(rs,s);   
1205         return rs;
1206         
1207     case AOP_REG:
1208       //if (dname) 
1209       //    return aop->aopu.aop_reg[offset]->dname;
1210       //else
1211             return aop->aopu.aop_reg[offset]->name;
1212         
1213     case AOP_CRY:
1214       //pic16_emitcode(";","%d",__LINE__);
1215       return aop->aopu.aop_dir;
1216         
1217     case AOP_ACC:
1218         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1219 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1220 //        assert( 0 );
1221         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1222
1223     case AOP_LIT:
1224         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1225         rs = Safe_calloc(1,strlen(s)+1);
1226         strcpy(rs,s);   
1227         return rs;
1228         
1229     case AOP_STR:
1230         aop->coff = offset ;
1231         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1232             dname)
1233             return "acc";
1234         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1235         
1236         return aop->aopu.aop_str[offset];
1237         
1238     case AOP_PCODE:
1239       {
1240         pCodeOp *pcop = aop->aopu.pcop;
1241         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1242         if(pcop->name) {
1243           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1244           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1245           sprintf(s,"%s", pcop->name);
1246         } else
1247           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1248
1249       }
1250       rs = Safe_calloc(1,strlen(s)+1);
1251       strcpy(rs,s);   
1252       return rs;
1253
1254     }
1255
1256     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1257            "aopget got unsupported aop->type");
1258     exit(0);
1259 }
1260
1261
1262 /*-----------------------------------------------------------------*/
1263 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1264 /*-----------------------------------------------------------------*/
1265 pCodeOp *pic16_popGetTempReg(void)
1266 {
1267   pCodeOp *pcop;
1268
1269         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1270         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1271                 PCOR(pcop)->r->wasUsed=1;
1272                 PCOR(pcop)->r->isFree=0;
1273
1274                 /* push value on stack */
1275                 pic16_pushpCodeOp( pcop );
1276         }
1277
1278   return pcop;
1279 }
1280
1281 /*-----------------------------------------------------------------*/
1282 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1283 /*-----------------------------------------------------------------*/
1284 void pic16_popReleaseTempReg(pCodeOp *pcop)
1285 {
1286         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1287                 PCOR(pcop)->r->isFree = 1;
1288                 
1289                 pic16_poppCodeOp( pcop );
1290         }
1291 }
1292 /*-----------------------------------------------------------------*/
1293 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1294 /*-----------------------------------------------------------------*/
1295 pCodeOp *pic16_popGetLabel(unsigned int key)
1296 {
1297
1298   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1299
1300   if(key>max_key)
1301     max_key = key;
1302
1303   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* pic16_popCopyReg - copy a pcode operator                              */
1308 /*-----------------------------------------------------------------*/
1309 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1310 {
1311   pCodeOpReg *pcor;
1312
1313   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1314   pcor->pcop.type = pc->pcop.type;
1315   if(pc->pcop.name) {
1316     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1317       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1318   } else
1319     pcor->pcop.name = NULL;
1320
1321   pcor->r = pc->r;
1322   pcor->rIdx = pc->rIdx;
1323   pcor->r->wasUsed=1;
1324
1325 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1326
1327   return PCOP(pcor);
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1332 /*-----------------------------------------------------------------*/
1333 pCodeOp *pic16_popGetLit(unsigned int lit)
1334 {
1335   return pic16_newpCodeOpLit(lit);
1336 }
1337
1338 /*-----------------------------------------------------------------*/
1339 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1340 /*-----------------------------------------------------------------*/
1341 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1342 {
1343   return pic16_newpCodeOpLit2(lit, arg2);
1344 }
1345
1346
1347 /*-----------------------------------------------------------------*/
1348 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1349 /*-----------------------------------------------------------------*/
1350 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1351 {
1352
1353   return pic16_newpCodeOpImmd(name, offset,index, 0);
1354 }
1355
1356
1357 /*-----------------------------------------------------------------*/
1358 /* pic16_popGet - asm operator to pcode operator conversion              */
1359 /*-----------------------------------------------------------------*/
1360 pCodeOp *pic16_popGetWithString(char *str)
1361 {
1362   pCodeOp *pcop;
1363
1364
1365   if(!str) {
1366     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1367     exit (1);
1368   }
1369
1370   pcop = pic16_newpCodeOp(str,PO_STR);
1371
1372   return pcop;
1373 }
1374
1375 /*-----------------------------------------------------------------*/
1376 /* pic16_popRegFromString -                                        */
1377 /*-----------------------------------------------------------------*/
1378 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1379 {
1380
1381   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1382   pcop->type = PO_DIR;
1383
1384   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1385 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1386
1387   if(!str)
1388     str = "BAD_STRING";
1389
1390   pcop->name = Safe_calloc(1,strlen(str)+1);
1391   strcpy(pcop->name,str);
1392
1393   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1394
1395   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1396   if(PCOR(pcop)->r == NULL) {
1397 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1398 //              __FUNCTION__, __LINE__, str, size, offset);
1399     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1400
1401         //fprintf(stderr, "allocating new register -> %s\n", str);
1402
1403 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1404   } else {
1405 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1406   }
1407   PCOR(pcop)->instance = offset;
1408
1409   return pcop;
1410 }
1411
1412 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1413 {
1414   pCodeOp *pcop;
1415
1416 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1417
1418         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1419         PCOR(pcop)->rIdx = rIdx;
1420         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1421         PCOR(pcop)->r->isFree = 0;
1422         PCOR(pcop)->r->wasUsed = 1;
1423
1424         pcop->type = PCOR(pcop)->r->pc_type;
1425
1426   return pcop;
1427 }
1428
1429 /*---------------------------------------------------------------------------------*/
1430 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1431 /*                 VR 030601                                                       */
1432 /*---------------------------------------------------------------------------------*/
1433 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1434 {
1435   pCodeOpReg2 *pcop2;
1436   pCodeOp *temp;
1437   
1438         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1439
1440         /* comment the following check, so errors to throw up */
1441 //      if(!pcop2)return NULL;
1442
1443         temp = pic16_popGet(aop_dst, offset);
1444         pcop2->pcop2 = temp;
1445         
1446   return PCOP(pcop2);
1447 }
1448
1449
1450
1451 /*--------------------------------------------------------------------------------.-*/
1452 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1453 /*                  VR 030601 , adapted by Hans Dorn                                */
1454 /*--------------------------------------------------------------------------------.-*/
1455 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1456 {
1457   pCodeOpReg2 *pcop2;
1458  
1459         pcop2 = (pCodeOpReg2 *)src;
1460         pcop2->pcop2 = dst;
1461         
1462         return PCOP(pcop2);
1463 }
1464
1465
1466
1467 /*---------------------------------------------------------------------------------*/
1468 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1469 /*                     movff instruction                                           */
1470 /*---------------------------------------------------------------------------------*/
1471 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1472 {
1473   pCodeOpReg2 *pcop2;
1474
1475         if(!noalloc) {
1476                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1477                 pcop2->pcop2 = pic16_popCopyReg(dst);
1478         } else {
1479                 /* the pCodeOp may be already allocated */
1480                 pcop2 = (pCodeOpReg2 *)(src);
1481                 pcop2->pcop2 = (pCodeOp *)(dst);
1482         }
1483
1484   return PCOP(pcop2);
1485 }
1486
1487
1488 /*-----------------------------------------------------------------*/
1489 /* pic16_popGet - asm operator to pcode operator conversion              */
1490 /*-----------------------------------------------------------------*/
1491 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1492 {
1493   //char *s = buffer ;
1494   char *rs;
1495   pCodeOp *pcop;
1496
1497     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1498     /* offset is greater than
1499     size then zero */
1500
1501 //    if (offset > (aop->size - 1) &&
1502 //        aop->type != AOP_LIT)
1503 //      return NULL;  //zero;
1504
1505     /* depending on type */
1506     switch (aop->type) {
1507         
1508     case AOP_R0:
1509     case AOP_R1:
1510     case AOP_DPTR:
1511     case AOP_DPTR2:
1512         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1513         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1514         assert( 0 );
1515         return NULL;
1516
1517
1518
1519     case AOP_IMMD:
1520       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1521       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1522
1523     case AOP_ACC:
1524       {
1525         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1526
1527         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1528
1529         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1530         
1531         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1532         PCOR(pcop)->rIdx = rIdx;
1533         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1534         PCOR(pcop)->r->wasUsed=1;
1535         PCOR(pcop)->r->isFree=0;
1536
1537         PCOR(pcop)->instance = offset;
1538         pcop->type = PCOR(pcop)->r->pc_type;
1539 //      rs = aop->aopu.aop_reg[offset]->name;
1540 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1541         return pcop;
1542
1543
1544 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1545 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1546
1547 //      assert( 0 );
1548       }
1549         
1550     case AOP_DIR:
1551       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1552       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1553         
1554     case AOP_REG:
1555       {
1556         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1557
1558         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1559         
1560         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1561         PCOR(pcop)->rIdx = rIdx;
1562         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1563         PCOR(pcop)->r->wasUsed=1;
1564         PCOR(pcop)->r->isFree=0;
1565
1566         PCOR(pcop)->instance = offset;
1567         pcop->type = PCOR(pcop)->r->pc_type;
1568         rs = aop->aopu.aop_reg[offset]->name;
1569         DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1570         return pcop;
1571       }
1572
1573     case AOP_CRY:
1574         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1575
1576       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1577       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1578       //if(PCOR(pcop)->r == NULL)
1579       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1580       return pcop;
1581         
1582     case AOP_LIT:
1583         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1584       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1585
1586     case AOP_STR:
1587       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1588       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1589
1590       /*
1591       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1592       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1593       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1594       pcop->type = PCOR(pcop)->r->pc_type;
1595       pcop->name = PCOR(pcop)->r->name;
1596
1597       return pcop;
1598       */
1599
1600     case AOP_PCODE:
1601       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1602                           __LINE__, 
1603                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1604       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1605 #if 1
1606         switch( aop->aopu.pcop->type ) {
1607                 case PO_DIR: PCOR(pcop)->instance = offset; break;
1608                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1609                 default:
1610                         assert( 0 );    /* should never reach here */;
1611         }
1612 #else
1613       PCOI(pcop)->offset = offset;
1614 #endif
1615       return pcop;
1616     }
1617
1618     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1619            "pic16_popGet got unsupported aop->type");
1620     exit(0);
1621 }
1622 /*-----------------------------------------------------------------*/
1623 /* pic16_aopPut - puts a string for a aop                                */
1624 /*-----------------------------------------------------------------*/
1625 void pic16_aopPut (asmop *aop, char *s, int offset)
1626 {
1627     char *d = buffer ;
1628     symbol *lbl ;
1629
1630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1631
1632     if (aop->size && offset > ( aop->size - 1)) {
1633         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1634                "pic16_aopPut got offset > aop->size");
1635         exit(0);
1636     }
1637
1638     /* will assign value to value */
1639     /* depending on where it is ofcourse */
1640     switch (aop->type) {
1641     case AOP_DIR:
1642       if (offset) {
1643         sprintf(d,"(%s + %d)",
1644                 aop->aopu.aop_dir,offset);
1645         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1646
1647       } else
1648             sprintf(d,"%s",aop->aopu.aop_dir);
1649         
1650         if (strcmp(d,s)) {
1651           DEBUGpic16_emitcode(";","%d",__LINE__);
1652           if(strcmp(s,"W"))
1653             pic16_emitcode("movf","%s,w",s);
1654           pic16_emitcode("movwf","%s",d);
1655
1656           if(strcmp(s,"W")) {
1657             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1658             if(offset >= aop->size) {
1659               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1660               break;
1661             } else
1662               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1663           }
1664
1665           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1666
1667
1668         }
1669         break;
1670         
1671     case AOP_REG:
1672       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1673         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1674           /*
1675             if (*s == '@'           ||
1676                 strcmp(s,"r0") == 0 ||
1677                 strcmp(s,"r1") == 0 ||
1678                 strcmp(s,"r2") == 0 ||
1679                 strcmp(s,"r3") == 0 ||
1680                 strcmp(s,"r4") == 0 ||
1681                 strcmp(s,"r5") == 0 ||
1682                 strcmp(s,"r6") == 0 || 
1683                 strcmp(s,"r7") == 0 )
1684                 pic16_emitcode("mov","%s,%s  ; %d",
1685                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1686             else
1687           */
1688
1689           if(strcmp(s,"W")==0 )
1690             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1691
1692           pic16_emitcode("movwf","%s",
1693                    aop->aopu.aop_reg[offset]->name);
1694
1695           if(strcmp(s,zero)==0) {
1696             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1697
1698           } else if(strcmp(s,"W")==0) {
1699             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1700             pcop->type = PO_GPR_REGISTER;
1701
1702             PCOR(pcop)->rIdx = -1;
1703             PCOR(pcop)->r = NULL;
1704
1705             DEBUGpic16_emitcode(";","%d",__LINE__);
1706             pcop->name = Safe_strdup(s);
1707             pic16_emitpcode(POC_MOVFW,pcop);
1708             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1709           } else if(strcmp(s,one)==0) {
1710             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1711             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1712           } else {
1713             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1714           }
1715         }
1716         break;
1717         
1718     case AOP_DPTR:
1719     case AOP_DPTR2:
1720     
1721     if (aop->type == AOP_DPTR2)
1722     {
1723         genSetDPTR(1);
1724     }
1725     
1726         if (aop->code) {
1727             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1728                    "pic16_aopPut writting to code space");
1729             exit(0);
1730         }
1731         
1732         while (offset > aop->coff) {
1733             aop->coff++;
1734             pic16_emitcode ("inc","dptr");
1735         }
1736         
1737         while (offset < aop->coff) {
1738             aop->coff-- ;
1739             pic16_emitcode("lcall","__decdptr");
1740         }
1741         
1742         aop->coff = offset;
1743         
1744         /* if not in accumulater */
1745         MOVA(s);        
1746         
1747         pic16_emitcode ("movx","@dptr,a");
1748         
1749     if (aop->type == AOP_DPTR2)
1750     {
1751         genSetDPTR(0);
1752     }
1753         break;
1754         
1755     case AOP_R0:
1756     case AOP_R1:
1757         while (offset > aop->coff) {
1758             aop->coff++;
1759             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1760         }
1761         while (offset < aop->coff) {
1762             aop->coff-- ;
1763             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1764         }
1765         aop->coff = offset;
1766         
1767         if (aop->paged) {
1768             MOVA(s);           
1769             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1770             
1771         } else
1772             if (*s == '@') {
1773                 MOVA(s);
1774                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1775             } else
1776                 if (strcmp(s,"r0") == 0 ||
1777                     strcmp(s,"r1") == 0 ||
1778                     strcmp(s,"r2") == 0 ||
1779                     strcmp(s,"r3") == 0 ||
1780                     strcmp(s,"r4") == 0 ||
1781                     strcmp(s,"r5") == 0 ||
1782                     strcmp(s,"r6") == 0 || 
1783                     strcmp(s,"r7") == 0 ) {
1784                     char buffer[10];
1785                     sprintf(buffer,"a%s",s);
1786                     pic16_emitcode("mov","@%s,%s",
1787                              aop->aopu.aop_ptr->name,buffer);
1788                 } else
1789                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1790         
1791         break;
1792         
1793     case AOP_STK:
1794         if (strcmp(s,"a") == 0)
1795             pic16_emitcode("push","acc");
1796         else
1797             pic16_emitcode("push","%s",s);
1798         
1799         break;
1800         
1801     case AOP_CRY:
1802         /* if bit variable */
1803         if (!aop->aopu.aop_dir) {
1804             pic16_emitcode("clr","a");
1805             pic16_emitcode("rlc","a");
1806         } else {
1807             if (s == zero) 
1808                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1809             else
1810                 if (s == one)
1811                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1812                 else
1813                     if (!strcmp(s,"c"))
1814                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1815                     else {
1816                         lbl = newiTempLabel(NULL);
1817                         
1818                         if (strcmp(s,"a")) {
1819                             MOVA(s);
1820                         }
1821                         pic16_emitcode("clr","c");
1822                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1823                         pic16_emitcode("cpl","c");
1824                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1825                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1826                     }
1827         }
1828         break;
1829         
1830     case AOP_STR:
1831         aop->coff = offset;
1832         if (strcmp(aop->aopu.aop_str[offset],s))
1833             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1834         break;
1835         
1836     case AOP_ACC:
1837         aop->coff = offset;
1838         if (!offset && (strcmp(s,"acc") == 0))
1839             break;
1840         
1841         if (strcmp(aop->aopu.aop_str[offset],s))
1842             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1843         break;
1844
1845     default :
1846         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1847                "pic16_aopPut got unsupported aop->type");
1848         exit(0);    
1849     }    
1850
1851 }
1852
1853 /*-----------------------------------------------------------------*/
1854 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1855 /*-----------------------------------------------------------------*/
1856 static void mov2w (asmop *aop, int offset)
1857 {
1858
1859   if(!aop)
1860     return;
1861
1862   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1863
1864   if ( aop->type == AOP_PCODE ||
1865        aop->type == AOP_LIT )
1866     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1867   else
1868     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1869
1870 }
1871
1872
1873 /* push pcop into stack */
1874 void pic16_pushpCodeOp(pCodeOp *pcop)
1875 {
1876         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1877 }
1878
1879 /* pop pcop from stack */
1880 void pic16_poppCodeOp(pCodeOp *pcop)
1881 {
1882         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1883 }
1884
1885
1886 /*-----------------------------------------------------------------*/
1887 /* pushw - pushes wreg to stack                                    */
1888 /*-----------------------------------------------------------------*/
1889 void pushw(void)
1890 {
1891         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1892         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1893 }
1894
1895                 
1896 /*-----------------------------------------------------------------*/
1897 /* pushaop - pushes aop to stack                                   */
1898 /*-----------------------------------------------------------------*/
1899 void pushaop(asmop *aop, int offset)
1900 {
1901         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1902         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1903 }
1904
1905 /*-----------------------------------------------------------------*/
1906 /* popaop - pops aop from stack                                    */
1907 /*-----------------------------------------------------------------*/
1908 void popaop(asmop *aop, int offset)
1909 {
1910         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1911         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1912 }
1913
1914 void popaopidx(asmop *aop, int offset, int index)
1915 {
1916   int ofs=1;
1917
1918         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1919
1920         if(STACK_MODEL_LARGE)ofs++;
1921
1922         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1923         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1924 }
1925
1926 /*-----------------------------------------------------------------*/
1927 /* reAdjustPreg - points a register back to where it should        */
1928 /*-----------------------------------------------------------------*/
1929 static void reAdjustPreg (asmop *aop)
1930 {
1931     int size ;
1932
1933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1934     aop->coff = 0;
1935     if ((size = aop->size) <= 1)
1936         return ;
1937     size-- ;
1938     switch (aop->type) {
1939         case AOP_R0 :
1940         case AOP_R1 :
1941             while (size--)
1942                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1943             break;          
1944         case AOP_DPTR :
1945         case AOP_DPTR2:
1946             if (aop->type == AOP_DPTR2)
1947             {
1948                 genSetDPTR(1);
1949             } 
1950             while (size--)
1951             {
1952                 pic16_emitcode("lcall","__decdptr");
1953             }
1954                 
1955             if (aop->type == AOP_DPTR2)
1956             {
1957                 genSetDPTR(0);
1958             }                
1959             break;  
1960
1961     }   
1962
1963 }
1964
1965
1966 #if 0
1967 /*-----------------------------------------------------------------*/
1968 /* opIsGptr: returns non-zero if the passed operand is             */   
1969 /* a generic pointer type.                                         */
1970 /*-----------------------------------------------------------------*/ 
1971 static int opIsGptr(operand *op)
1972 {
1973     sym_link *type = operandType(op);
1974     
1975     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1976     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1977     {
1978         return 1;
1979     }
1980     return 0;        
1981 }
1982 #endif
1983
1984 /*-----------------------------------------------------------------*/
1985 /* pic16_getDataSize - get the operand data size                         */
1986 /*-----------------------------------------------------------------*/
1987 int pic16_getDataSize(operand *op)
1988 {
1989     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1990
1991
1992     return AOP_SIZE(op);
1993
1994     // tsd- in the pic port, the genptr size is 1, so this code here
1995     // fails. ( in the 8051 port, the size was 4).
1996 #if 0
1997     int size;
1998     size = AOP_SIZE(op);
1999     if (size == GPTRSIZE)
2000     {
2001         sym_link *type = operandType(op);
2002         if (IS_GENPTR(type))
2003         {
2004             /* generic pointer; arithmetic operations
2005              * should ignore the high byte (pointer type).
2006              */
2007             size--;
2008     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2009         }
2010     }
2011     return size;
2012 #endif
2013 }
2014
2015 /*-----------------------------------------------------------------*/
2016 /* pic16_outAcc - output Acc                                             */
2017 /*-----------------------------------------------------------------*/
2018 void pic16_outAcc(operand *result)
2019 {
2020   int size,offset;
2021   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2022   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2023
2024
2025   size = pic16_getDataSize(result);
2026   if(size){
2027     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2028     size--;
2029     offset = 1;
2030     /* unsigned or positive */
2031     while(size--)
2032       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2033   }
2034
2035 }
2036
2037 /*-----------------------------------------------------------------*/
2038 /* pic16_outBitC - output a bit C                                        */
2039 /*-----------------------------------------------------------------*/
2040 void pic16_outBitC(operand *result)
2041 {
2042
2043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2044     /* if the result is bit */
2045     if (AOP_TYPE(result) == AOP_CRY) 
2046         pic16_aopPut(AOP(result),"c",0);
2047     else {
2048         pic16_emitcode("clr","a  ; %d", __LINE__);
2049         pic16_emitcode("rlc","a");
2050         pic16_outAcc(result);
2051     }
2052 }
2053
2054 /*-----------------------------------------------------------------*/
2055 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2056 /*-----------------------------------------------------------------*/
2057 void pic16_toBoolean(operand *oper)
2058 {
2059     int size = AOP_SIZE(oper) - 1;
2060     int offset = 1;
2061
2062     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2063
2064     if ( AOP_TYPE(oper) != AOP_ACC) {
2065       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2066     }
2067     while (size--) {
2068       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2069     }
2070 }
2071
2072
2073 #if !defined(GEN_Not)
2074 /*-----------------------------------------------------------------*/
2075 /* genNot - generate code for ! operation                          */
2076 /*-----------------------------------------------------------------*/
2077 static void pic16_genNot (iCode *ic)
2078 {
2079   symbol *tlbl;
2080   int size;
2081
2082   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2083   /* assign asmOps to operand & result */
2084   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2085   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2086
2087   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2088   /* if in bit space then a special case */
2089   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2090     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2091       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2092       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2093     } else {
2094       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2095       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2096       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2097     }
2098     goto release;
2099   }
2100
2101   size = AOP_SIZE(IC_LEFT(ic));
2102   if(size == 1) {
2103     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2104     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2105     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2106     goto release;
2107   }
2108   pic16_toBoolean(IC_LEFT(ic));
2109
2110   tlbl = newiTempLabel(NULL);
2111   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2112   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2113   pic16_outBitC(IC_RESULT(ic));
2114
2115  release:    
2116   /* release the aops */
2117   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2118   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2119 }
2120 #endif
2121
2122
2123 #if !defined(GEN_Cpl)
2124 /*-----------------------------------------------------------------*/
2125 /* genCpl - generate code for complement                           */
2126 /*-----------------------------------------------------------------*/
2127 static void pic16_genCpl (iCode *ic)
2128 {
2129     int offset = 0;
2130     int size ;
2131
2132
2133     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2134     /* assign asmOps to operand & result */
2135     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2136     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2137
2138     /* if both are in bit space then 
2139     a special case */
2140     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2141         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2142
2143         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2144         pic16_emitcode("cpl","c"); 
2145         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2146         goto release; 
2147     } 
2148
2149     size = AOP_SIZE(IC_RESULT(ic));
2150     while (size--) {
2151 /*
2152         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2153         MOVA(l);       
2154         pic16_emitcode("cpl","a");
2155         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2156 */
2157         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2158               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2159         } else {
2160                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2161                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2162         }
2163         offset++;
2164
2165     }
2166
2167
2168 release:
2169     /* release the aops */
2170     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2171     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2172 }
2173 #endif
2174
2175 /*-----------------------------------------------------------------*/
2176 /* genUminusFloat - unary minus for floating points                */
2177 /*-----------------------------------------------------------------*/
2178 static void genUminusFloat(operand *op,operand *result)
2179 {
2180     int size ,offset =0 ;
2181     char *l;
2182
2183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2184     /* for this we just need to flip the 
2185     first it then copy the rest in place */
2186     size = AOP_SIZE(op) - 1;
2187     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2188
2189     MOVA(l);    
2190
2191     pic16_emitcode("cpl","acc.7");
2192     pic16_aopPut(AOP(result),"a",3);    
2193
2194     while(size--) {
2195         pic16_aopPut(AOP(result),
2196                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2197                offset);
2198         offset++;
2199     }          
2200 }
2201
2202 /*-----------------------------------------------------------------*/
2203 /* genUminus - unary minus code generation                         */
2204 /*-----------------------------------------------------------------*/
2205 static void genUminus (iCode *ic)
2206 {
2207   int size, i;
2208   sym_link *optype, *rtype;
2209
2210
2211   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2212   /* assign asmops */
2213   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2214   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2215
2216   /* if both in bit space then special
2217      case */
2218   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2219       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2220
2221     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2222     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2223     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2224
2225     goto release; 
2226   } 
2227
2228   optype = operandType(IC_LEFT(ic));
2229   rtype = operandType(IC_RESULT(ic));
2230
2231   /* if float then do float stuff */
2232   if (IS_FLOAT(optype)) {
2233     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2234     goto release;
2235   }
2236
2237   /* otherwise subtract from zero by taking the 2's complement */
2238   size = AOP_SIZE(IC_LEFT(ic));
2239
2240   for(i=0; i<size; i++) {
2241     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2242       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2243     else {
2244       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2245       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2246     }
2247   }
2248
2249   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2250   for(i=1; i<size; i++) {
2251     emitSKPNZ;
2252     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2253   }
2254
2255  release:
2256   /* release the aops */
2257   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2258   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2259 }
2260
2261 /*-----------------------------------------------------------------*/
2262 /* saveRegisters - will look for a call and save the registers     */
2263 /*-----------------------------------------------------------------*/
2264 static void saveRegisters(iCode *lic) 
2265 {
2266     int i;
2267     iCode *ic;
2268     bitVect *rsave;
2269     sym_link *dtype;
2270
2271     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272     /* look for call */
2273     for (ic = lic ; ic ; ic = ic->next) 
2274         if (ic->op == CALL || ic->op == PCALL)
2275             break;
2276
2277     if (!ic) {
2278         fprintf(stderr,"found parameter push with no function call\n");
2279         return ;
2280     }
2281
2282     /* if the registers have been saved already then
2283     do nothing */
2284     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2285         return ;
2286
2287     /* find the registers in use at this time 
2288     and push them away to safety */
2289     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2290                           ic->rUsed);
2291
2292     ic->regsSaved = 1;
2293     if (options.useXstack) {
2294         if (bitVectBitValue(rsave,R0_IDX))
2295             pic16_emitcode("mov","b,r0");
2296         pic16_emitcode("mov","r0,%s",spname);
2297         for (i = 0 ; i < pic16_nRegs ; i++) {
2298             if (bitVectBitValue(rsave,i)) {
2299                 if (i == R0_IDX)
2300                     pic16_emitcode("mov","a,b");
2301                 else
2302                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2303                 pic16_emitcode("movx","@r0,a");
2304                 pic16_emitcode("inc","r0");
2305             }
2306         }
2307         pic16_emitcode("mov","%s,r0",spname);
2308         if (bitVectBitValue(rsave,R0_IDX))
2309             pic16_emitcode("mov","r0,b");           
2310     }// else
2311     //for (i = 0 ; i < pic16_nRegs ; i++) {
2312     //    if (bitVectBitValue(rsave,i))
2313     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2314     //}
2315
2316     dtype = operandType(IC_LEFT(ic));
2317     if (currFunc && dtype && 
2318         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2319         IFFUNC_ISISR(currFunc->type) &&
2320         !ic->bankSaved) 
2321
2322         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2323
2324 }
2325 /*-----------------------------------------------------------------*/
2326 /* unsaveRegisters - pop the pushed registers                      */
2327 /*-----------------------------------------------------------------*/
2328 static void unsaveRegisters (iCode *ic)
2329 {
2330     int i;
2331     bitVect *rsave;
2332
2333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334     /* find the registers in use at this time 
2335     and push them away to safety */
2336     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2337                           ic->rUsed);
2338     
2339     if (options.useXstack) {
2340         pic16_emitcode("mov","r0,%s",spname);   
2341         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2342             if (bitVectBitValue(rsave,i)) {
2343                 pic16_emitcode("dec","r0");
2344                 pic16_emitcode("movx","a,@r0");
2345                 if (i == R0_IDX)
2346                     pic16_emitcode("mov","b,a");
2347                 else
2348                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2349             }       
2350
2351         }
2352         pic16_emitcode("mov","%s,r0",spname);
2353         if (bitVectBitValue(rsave,R0_IDX))
2354             pic16_emitcode("mov","r0,b");
2355     } //else
2356     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2357     //    if (bitVectBitValue(rsave,i))
2358     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2359     //}
2360
2361 }  
2362
2363
2364 /*-----------------------------------------------------------------*/
2365 /* pushSide -                                                      */
2366 /*-----------------------------------------------------------------*/
2367 static void pushSide(operand * oper, int size)
2368 {
2369 #if 0
2370         int offset = 0;
2371     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2372         while (size--) {
2373                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2374                 if (AOP_TYPE(oper) != AOP_REG &&
2375                     AOP_TYPE(oper) != AOP_DIR &&
2376                     strcmp(l,"a") ) {
2377                         pic16_emitcode("mov","a,%s",l);
2378                         pic16_emitcode("push","acc");
2379                 } else
2380                         pic16_emitcode("push","%s",l);
2381         }
2382 #endif
2383 }
2384
2385 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2386 {
2387 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2388
2389         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2390                 pic16_emitpcode(POC_MOVFW, src);
2391                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2392         } else {
2393                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2394                         src, pic16_popGet(AOP(op), offset)));
2395         }
2396 }
2397
2398
2399 /*-----------------------------------------------------------------*/
2400 /* assignResultValue - assign results to oper, rescall==1 is       */
2401 /*                     called from genCall() or genPCall()         */
2402 /*-----------------------------------------------------------------*/
2403 static void assignResultValue(operand * oper, int rescall)
2404 {
2405   int size = AOP_SIZE(oper);
2406
2407         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2408         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2409
2410         if(rescall) {
2411                 /* assign result from a call/pcall function() */
2412                 
2413                 /* function results are stored in a special order,
2414                  * see top of file with Function return policy, or manual */
2415
2416                 if(size <= 4) {
2417                         /* 8-bits, result in WREG */
2418                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2419                         
2420                         if(size>1) {
2421                                 /* 16-bits, result in PRODL:WREG */
2422                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2423 //                              pic16_emitpcode(POC_MOVFF,
2424 //                                      pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(oper), 1)));
2425                         }
2426                         
2427                         if(size>2) {
2428                                 /* 24-bits, result in PRODH:PRODL:WREG */
2429                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodl));
2430
2431 //                              pic16_emitpcode(POC_MOVFF,
2432 //                                      pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(oper), 2)));
2433                         }
2434                         
2435                         if(size>3) {
2436                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2437                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_prodl));
2438
2439 //                              pic16_emitpcode(POC_MOVFF,
2440 //                                      pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popGet(AOP(oper), 3)));
2441                         }
2442                 } else {
2443                         /* >32-bits, result on stack, and FSR0 points to beginning.
2444                          * Fix stack when done */
2445                          
2446                         while (size--) {
2447 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2448 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2449                 
2450                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2451                                 GpsuedoStkPtr++;
2452                         }
2453                         
2454                         /* fix stack */
2455                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2456                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2457                         if(STACK_MODEL_LARGE) {
2458                                 emitSKPNC;
2459                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2460                         }
2461                 }                       
2462         } else {
2463                 if(!GpsuedoStkPtr) {
2464 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2465                         /* The last byte in the assignment is in W */
2466                         size--;
2467                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2468                         GpsuedoStkPtr++;
2469                 }
2470
2471                 while (size--) {
2472 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2473 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2474                 
2475                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2476                         GpsuedoStkPtr++;
2477
2478 #if 0
2479 #if STACK_SUPPORT
2480                 if(!USE_STACK)
2481                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2482 #else
2483                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2484 #endif
2485 #endif
2486
2487                 }
2488         }
2489                 
2490 }
2491
2492
2493 /*-----------------------------------------------------------------*/
2494 /* genIpush - genrate code for pushing this gets a little complex  */
2495 /*-----------------------------------------------------------------*/
2496 static void genIpush (iCode *ic)
2497 {
2498
2499   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2500 #if 0
2501     int size, offset = 0 ;
2502     char *l;
2503
2504
2505     /* if this is not a parm push : ie. it is spill push 
2506     and spill push is always done on the local stack */
2507     if (!ic->parmPush) {
2508
2509         /* and the item is spilt then do nothing */
2510         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2511             return ;
2512
2513         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2514         size = AOP_SIZE(IC_LEFT(ic));
2515         /* push it on the stack */
2516         while(size--) {
2517             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2518             if (*l == '#') {
2519                 MOVA(l);
2520                 l = "acc";
2521             }
2522             pic16_emitcode("push","%s",l);
2523         }
2524         return ;        
2525     }
2526
2527     /* this is a paramter push: in this case we call
2528     the routine to find the call and save those
2529     registers that need to be saved */   
2530     saveRegisters(ic);
2531
2532     /* then do the push */
2533     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2534
2535
2536         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2537     size = AOP_SIZE(IC_LEFT(ic));
2538
2539     while (size--) {
2540         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2541         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2542             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2543             strcmp(l,"a") ) {
2544             pic16_emitcode("mov","a,%s",l);
2545             pic16_emitcode("push","acc");
2546         } else
2547             pic16_emitcode("push","%s",l);
2548     }       
2549
2550     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2551 #endif
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* genIpop - recover the registers: can happen only for spilling   */
2556 /*-----------------------------------------------------------------*/
2557 static void genIpop (iCode *ic)
2558 {
2559   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2560 #if 0
2561     int size,offset ;
2562
2563
2564     /* if the temp was not pushed then */
2565     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2566         return ;
2567
2568     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2569     size = AOP_SIZE(IC_LEFT(ic));
2570     offset = (size-1);
2571     while (size--) 
2572         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2573                                    FALSE,TRUE));
2574
2575     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2576 #endif
2577 }
2578
2579 /*-----------------------------------------------------------------*/
2580 /* unsaverbank - restores the resgister bank from stack            */
2581 /*-----------------------------------------------------------------*/
2582 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2583 {
2584   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2585 #if 0
2586     int i;
2587     asmop *aop ;
2588     regs *r = NULL;
2589
2590     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2591     if (popPsw) {
2592         if (options.useXstack) {
2593             aop = newAsmop(0);
2594             r = getFreePtr(ic,&aop,FALSE);
2595             
2596             
2597             pic16_emitcode("mov","%s,_spx",r->name);
2598             pic16_emitcode("movx","a,@%s",r->name);
2599             pic16_emitcode("mov","psw,a");
2600             pic16_emitcode("dec","%s",r->name);
2601             
2602         }else
2603             pic16_emitcode ("pop","psw");
2604     }
2605
2606     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2607         if (options.useXstack) {       
2608             pic16_emitcode("movx","a,@%s",r->name);
2609             //pic16_emitcode("mov","(%s+%d),a",
2610             //       regspic16[i].base,8*bank+regspic16[i].offset);
2611             pic16_emitcode("dec","%s",r->name);
2612
2613         } else 
2614           pic16_emitcode("pop",""); //"(%s+%d)",
2615         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2616     }
2617
2618     if (options.useXstack) {
2619
2620         pic16_emitcode("mov","_spx,%s",r->name);
2621         pic16_freeAsmop(NULL,aop,ic,TRUE);
2622
2623     }
2624 #endif 
2625 }
2626
2627 /*-----------------------------------------------------------------*/
2628 /* saverbank - saves an entire register bank on the stack          */
2629 /*-----------------------------------------------------------------*/
2630 static void saverbank (int bank, iCode *ic, bool pushPsw)
2631 {
2632   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2633 #if 0
2634     int i;
2635     asmop *aop ;
2636     regs *r = NULL;
2637
2638     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2639     if (options.useXstack) {
2640
2641         aop = newAsmop(0);
2642         r = getFreePtr(ic,&aop,FALSE);  
2643         pic16_emitcode("mov","%s,_spx",r->name);
2644
2645     }
2646
2647     for (i = 0 ; i < pic16_nRegs ;i++) {
2648         if (options.useXstack) {
2649             pic16_emitcode("inc","%s",r->name);
2650             //pic16_emitcode("mov","a,(%s+%d)",
2651             //         regspic16[i].base,8*bank+regspic16[i].offset);
2652             pic16_emitcode("movx","@%s,a",r->name);           
2653         } else 
2654           pic16_emitcode("push","");// "(%s+%d)",
2655                      //regspic16[i].base,8*bank+regspic16[i].offset);
2656     }
2657     
2658     if (pushPsw) {
2659         if (options.useXstack) {
2660             pic16_emitcode("mov","a,psw");
2661             pic16_emitcode("movx","@%s,a",r->name);     
2662             pic16_emitcode("inc","%s",r->name);
2663             pic16_emitcode("mov","_spx,%s",r->name);       
2664             pic16_freeAsmop (NULL,aop,ic,TRUE);
2665             
2666         } else
2667             pic16_emitcode("push","psw");
2668         
2669         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2670     }
2671     ic->bankSaved = 1;
2672 #endif
2673 }
2674
2675
2676
2677 /*-----------------------------------------------------------------*/
2678 /* genCall - generates a call statement                            */
2679 /*-----------------------------------------------------------------*/
2680 static void genCall (iCode *ic)
2681 {
2682   sym_link *dtype;   
2683   int stackParms=0;
2684   
2685         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2686
2687         /* if caller saves & we have not saved then */
2688         if (!ic->regsSaved)
2689                 saveRegisters(ic);
2690
2691         /* if we are calling a function that is not using
2692          * the same register bank then we need to save the
2693          * destination registers on the stack */
2694         dtype = operandType(IC_LEFT(ic));
2695         if (currFunc && dtype && 
2696                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2697                 IFFUNC_ISISR(currFunc->type) &&
2698                 !ic->bankSaved) 
2699
2700                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2701
2702         /* if send set is not empty the assign */
2703         if (_G.sendSet) {
2704           iCode *sic;
2705
2706                 /* For the Pic port, there is no data stack.
2707                  * So parameters passed to functions are stored
2708                  * in registers. (The pCode optimizer will get
2709                  * rid of most of these :). */
2710
2711           int psuedoStkPtr=-1; 
2712           int firstTimeThruLoop = 1;
2713
2714                 _G.sendSet = reverseSet(_G.sendSet);
2715
2716                 /* First figure how many parameters are getting passed */
2717                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2718                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2719                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2720                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2721                 }
2722
2723                 stackParms = psuedoStkPtr;
2724
2725                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2726                   int size, offset = 0;
2727
2728                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2729                         size = AOP_SIZE(IC_LEFT(sic));
2730
2731                         while (size--) {
2732                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2733                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2734                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2735
2736                                 if(!firstTimeThruLoop) {
2737                                         /* If this is not the first time we've been through the loop
2738                                          * then we need to save the parameter in a temporary
2739                                          * register. The last byte of the last parameter is
2740                                          * passed in W. */
2741
2742                                         pushw();
2743                                         --psuedoStkPtr;         // sanity check
2744                                 }
2745                         
2746                                 firstTimeThruLoop=0;
2747
2748                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2749                                 offset++;
2750                         }
2751                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2752                 }
2753                 _G.sendSet = NULL;
2754         }
2755
2756         /* make the call */
2757         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2758                         OP_SYMBOL(IC_LEFT(ic))->rname :
2759                         OP_SYMBOL(IC_LEFT(ic))->name));
2760
2761         GpsuedoStkPtr=0;
2762         /* if we need assign a result value */
2763         if ((IS_ITEMP(IC_RESULT(ic)) && 
2764                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2765                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2766                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2767
2768                 _G.accInUse++;
2769                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2770                 _G.accInUse--;
2771
2772                 assignResultValue(IC_RESULT(ic), 1);
2773
2774                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2775                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2776                 
2777                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2778         }
2779
2780         if(stackParms>0) {
2781                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2782                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2783                 if(STACK_MODEL_LARGE) {
2784                         emitSKPNC;
2785                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2786                 }
2787         }
2788
2789         /* adjust the stack for parameters if required */
2790 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2791
2792         if (ic->parmBytes) {
2793           int i;
2794
2795                 if (ic->parmBytes > 3) {
2796                         pic16_emitcode("mov","a,%s",spname);
2797                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2798                         pic16_emitcode("mov","%s,a",spname);
2799                 } else 
2800                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2801                                 pic16_emitcode("dec","%s",spname);
2802         }
2803
2804         /* if register bank was saved then pop them */
2805         if (ic->bankSaved)
2806                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2807
2808         /* if we hade saved some registers then unsave them */
2809         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2810                 unsaveRegisters (ic);
2811 }
2812
2813 /*-----------------------------------------------------------------*/
2814 /* genPcall - generates a call by pointer statement                */
2815 /*-----------------------------------------------------------------*/
2816 static void genPcall (iCode *ic)
2817 {
2818     sym_link *dtype;
2819     symbol *rlbl = newiTempLabel(NULL);
2820
2821
2822     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2823     /* if caller saves & we have not saved then */
2824     if (!ic->regsSaved)
2825         saveRegisters(ic);
2826
2827     /* if we are calling a function that is not using
2828     the same register bank then we need to save the
2829     destination registers on the stack */
2830     dtype = operandType(IC_LEFT(ic));
2831     if (currFunc && dtype && 
2832         IFFUNC_ISISR(currFunc->type) &&
2833         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2834         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2835
2836
2837     /* push the return address on to the stack */
2838     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2839     pic16_emitcode("push","acc");    
2840     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2841     pic16_emitcode("push","acc");
2842     
2843     if (options.model == MODEL_FLAT24)
2844     {
2845         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2846         pic16_emitcode("push","acc");    
2847     }
2848
2849     /* now push the calling address */
2850     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2851
2852     pushSide(IC_LEFT(ic), FPTRSIZE);
2853
2854     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2855
2856     /* if send set is not empty the assign */
2857     if (_G.sendSet) {
2858         iCode *sic ;
2859
2860         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2861              sic = setNextItem(_G.sendSet)) {
2862             int size, offset = 0;
2863             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2864             size = AOP_SIZE(IC_LEFT(sic));
2865             while (size--) {
2866                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2867                                 FALSE,FALSE);
2868                 if (strcmp(l,fReturn[offset]))
2869                     pic16_emitcode("mov","%s,%s",
2870                              fReturn[offset],
2871                              l);
2872                 offset++;
2873             }
2874             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2875         }
2876         _G.sendSet = NULL;
2877     }
2878
2879     pic16_emitcode("ret","");
2880     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2881
2882
2883     /* if we need assign a result value */
2884     if ((IS_ITEMP(IC_RESULT(ic)) &&
2885          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2886           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2887         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2888
2889         _G.accInUse++;
2890         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2891         _G.accInUse--;
2892         
2893         assignResultValue(IC_RESULT(ic), 1);
2894
2895         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2896     }
2897
2898     /* adjust the stack for parameters if 
2899     required */
2900     if (ic->parmBytes) {
2901         int i;
2902         if (ic->parmBytes > 3) {
2903             pic16_emitcode("mov","a,%s",spname);
2904             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2905             pic16_emitcode("mov","%s,a",spname);
2906         } else 
2907             for ( i = 0 ; i <  ic->parmBytes ;i++)
2908                 pic16_emitcode("dec","%s",spname);
2909
2910     }
2911
2912     /* if register bank was saved then unsave them */
2913     if (currFunc && dtype && 
2914         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2915         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2916
2917     /* if we hade saved some registers then
2918     unsave them */
2919     if (ic->regsSaved)
2920         unsaveRegisters (ic);
2921
2922 }
2923
2924 /*-----------------------------------------------------------------*/
2925 /* resultRemat - result  is rematerializable                       */
2926 /*-----------------------------------------------------------------*/
2927 static int resultRemat (iCode *ic)
2928 {
2929   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2930   if (SKIP_IC(ic) || ic->op == IFX)
2931     return 0;
2932
2933   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2934     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2935     if (sym->remat && !POINTER_SET(ic)) 
2936       return 1;
2937   }
2938
2939   return 0;
2940 }
2941
2942 #if defined(__BORLANDC__) || defined(_MSC_VER)
2943 #define STRCASECMP stricmp
2944 #else
2945 #define STRCASECMP strcasecmp
2946 #endif
2947
2948 #if 0
2949 /*-----------------------------------------------------------------*/
2950 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2951 /*-----------------------------------------------------------------*/
2952 static bool inExcludeList(char *s)
2953 {
2954   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2955     int i =0;
2956     
2957     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2958     if (options.excludeRegs[i] &&
2959     STRCASECMP(options.excludeRegs[i],"none") == 0)
2960         return FALSE ;
2961
2962     for ( i = 0 ; options.excludeRegs[i]; i++) {
2963         if (options.excludeRegs[i] &&
2964         STRCASECMP(s,options.excludeRegs[i]) == 0)
2965             return TRUE;
2966     }
2967     return FALSE ;
2968 }
2969 #endif
2970
2971 /*-----------------------------------------------------------------*/
2972 /* genFunction - generated code for function entry                 */
2973 /*-----------------------------------------------------------------*/
2974 static void genFunction (iCode *ic)
2975 {
2976   symbol *sym;
2977   sym_link *ftype;
2978
2979         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2980
2981         labelOffset += (max_key+4);
2982         max_key=0;
2983         GpsuedoStkPtr=0;
2984         _G.nRegsSaved = 0;
2985
2986         ftype = operandType(IC_LEFT(ic));
2987
2988         if(/*!IFFUNC_ISNAKED(ftype) &&*/ IFFUNC_ISISR(ftype)) {
2989                 /* create an absolute section at the interrupt vector:
2990                  * that is 0x0008 for interrupt 1, 0x0018 interrupt 2 */
2991           int ivec;
2992           symbol *asym;
2993           char asymname[128];
2994           
2995                 {
2996                   int i;
2997
2998                         sym = OP_SYMBOL( IC_LEFT(ic));
2999                         for(i=1;i<=2;i++)
3000                                 if(STRCASECMP(interrupts[i]->name, sym->name))break;
3001                         
3002                         if(i>2) {
3003                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3004                                         __FILE__, __LINE__, sym->name);
3005                                 exit(-1);
3006                         }
3007                         ivec = i;
3008                 }
3009                 sprintf(asymname, "ivec_%s", sym->name);
3010                 asym = newSymbol(asymname, 0);
3011                 pic16_emitcode(";","-----------------------------------------");
3012                 pic16_emitcode(";"," interrupt vector %d for function %s", ivec, sym->name);
3013                 pic16_emitcode(";","-----------------------------------------");
3014                 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(moduleName, asym->name));
3015                 pic16_emitpcode(POC_GOTO, pic16_popGetWithString( sym->rname ));
3016                 
3017                 pic16_pBlockConvert2Absolute(pb);
3018         }
3019
3020
3021         /* create the function header */
3022         pic16_emitcode(";","-----------------------------------------");
3023         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
3024         pic16_emitcode(";","-----------------------------------------");
3025
3026         pic16_emitcode("","%s:",sym->rname);
3027         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3028
3029         {
3030           absSym *ab;
3031
3032                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3033                         if(strcmp(ab->name, sym->name)) {
3034                                 pic16_pBlockConvert2Absolute(pb);
3035                                 break;
3036                         }
3037                 
3038         }
3039
3040
3041         if(IFFUNC_ISNAKED(ftype)) {
3042                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3043                 return;
3044         }
3045         
3046         /* if critical function then turn interrupts off */
3047         if (IFFUNC_ISCRITICAL(ftype))
3048                 pic16_emitcode("clr","ea");
3049
3050         /* if this is an interrupt service routine then
3051          * save acc, b, dpl, dph  */
3052         if (IFFUNC_ISISR(sym->type)) {
3053           int i;
3054                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH */
3055                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3056                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3057                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3058                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3059                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3060                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3061                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3062
3063
3064 #if 0
3065                 /* VR -- this is the old code which clears STATUS register for
3066                  * the ISR routine. Why? */
3067                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
3068                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
3069                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3070                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
3071 #endif
3072
3073                 pic16_pBlockConvert2ISR(pb);
3074
3075 #if 0
3076                 if (!inExcludeList("acc"))          
3077                         pic16_emitcode ("push","acc");  
3078                 if (!inExcludeList("b"))
3079                         pic16_emitcode ("push","b");
3080                 if (!inExcludeList("dpl"))
3081                         pic16_emitcode ("push","dpl");
3082                 if (!inExcludeList("dph"))
3083                         pic16_emitcode ("push","dph");
3084 #endif
3085
3086                 /* if any registers used */
3087                 if (sym->regsUsed) {
3088                         /* save the registers used */
3089                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3090                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3091                                 if (bitVectBitValue(sym->regsUsed,i)) {
3092 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3093 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3094 //                                                      pic16_regWithIdx(i)->name);
3095
3096                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3097                                         _G.nRegsSaved++;
3098                                 }
3099                         }
3100                 }
3101         } else {
3102                 /* emit code to setup stack frame if user enabled,
3103                  * and function is not main() */
3104          
3105 //              fprintf(stderr, "function name: %s\n", sym->name);
3106                 if(strcmp(sym->name, "main")) {
3107                         if(!options.ommitFramePtr || sym->regsUsed) {
3108                         /* setup the stack frame */
3109                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3110                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3111                                 if(STACK_MODEL_LARGE)
3112                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3113                         }
3114                 }
3115
3116                 /* if callee-save to be used for this function
3117                 * then save the registers being used in this function */
3118                 if (IFFUNC_CALLEESAVES(sym->type)) {
3119                   int i;
3120             
3121 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
3122                         
3123                         /* if any registers used */
3124                         if (sym->regsUsed) {
3125                                 /* save the registers used */
3126                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3127                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3128                                         if (bitVectBitValue(sym->regsUsed,i)) {
3129 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3130 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3131 //                                                              pic16_regWithIdx(i)->name);
3132
3133                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3134 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3135 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3136 //                                                      &pic16_pc_postdec1, 0));
3137                                                 _G.nRegsSaved++;
3138                                         }
3139                                 }
3140                         }
3141                 }
3142         }
3143
3144
3145         
3146 #if 0
3147         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3148
3149                 if (options.useXstack) {
3150                         pic16_emitcode("mov","r0,%s",spname);
3151                         pic16_emitcode("mov","a,_bp");
3152                         pic16_emitcode("movx","@r0,a");
3153                         pic16_emitcode("inc","%s",spname);
3154                 } else {
3155                         /* set up the stack */
3156                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3157                 }
3158                 pic16_emitcode ("mov","_bp,%s",spname);
3159         }
3160 #endif
3161         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3162
3163         /* adjust the stack for the function */
3164         if (sym->stack) {
3165           int i = sym->stack;
3166
3167                 if (i > 127 ) 
3168                         werror(W_STACK_OVERFLOW,sym->name);
3169
3170                 if (i > 3 && sym->recvSize < 4) {              
3171                         pic16_emitcode ("mov","a,sp");
3172                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3173                         pic16_emitcode ("mov","sp,a");
3174                 } else
3175                         while(i--)
3176                                 pic16_emitcode("inc","sp");
3177         }
3178
3179         if (sym->xstack) {
3180                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3181
3182                 pic16_emitcode ("mov","a,_spx");
3183                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3184                 pic16_emitcode ("mov","_spx,a");
3185         }
3186     
3187 }
3188
3189 /*-----------------------------------------------------------------*/
3190 /* genEndFunction - generates epilogue for functions               */
3191 /*-----------------------------------------------------------------*/
3192 static void genEndFunction (iCode *ic)
3193 {
3194     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3195
3196     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3197
3198     if(IFFUNC_ISNAKED(sym->type)) {
3199         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3200         return;
3201     }
3202
3203 #if 0
3204     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3205     {
3206         pic16_emitcode ("mov","%s,_bp",spname);
3207     }
3208 #endif
3209
3210     /* if use external stack but some variables were
3211     added to the local stack then decrement the
3212     local stack */
3213     if (options.useXstack && sym->stack) {      
3214         pic16_emitcode("mov","a,sp");
3215         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3216         pic16_emitcode("mov","sp,a");
3217     }
3218
3219
3220 #if 0
3221     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3222         if (options.useXstack) {
3223             pic16_emitcode("mov","r0,%s",spname);
3224             pic16_emitcode("movx","a,@r0");
3225             pic16_emitcode("mov","_bp,a");
3226             pic16_emitcode("dec","%s",spname);
3227         }
3228         else
3229         {
3230             pic16_emitcode ("pop","_bp");
3231         }
3232     }
3233 #endif
3234
3235     /* restore the register bank  */    
3236     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3237         pic16_emitcode ("pop","psw");
3238
3239         if (IFFUNC_ISISR(sym->type)) {
3240
3241                 /* now we need to restore the registers */
3242                 
3243                 /* if any registers used */
3244                 if (sym->regsUsed) {
3245                   int i;
3246
3247                         /* restore registers used */
3248                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3249                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3250                                 if (bitVectBitValue(sym->regsUsed,i)) {
3251 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3252 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3253 //                                                      pic16_regWithIdx(i)->name);
3254         
3255                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3256                                                         &pic16_pc_preinc1,
3257                                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3258                                 }
3259                         }
3260                 }
3261         
3262                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3263                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3264                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3265                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3266                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3267                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3268                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3269         
3270
3271                 /* if debug then send end of function */
3272 /*      if (options.debug && currFunc)  */
3273                 if (currFunc) {
3274                         _G.debugLine = 1;
3275                         pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3276                                         FileBaseName(ic->filename),currFunc->lastLine,
3277                                         ic->level,ic->block); 
3278                         if (IS_STATIC(currFunc->etype))     
3279                                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3280                         else
3281                                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3282                         _G.debugLine = 0;
3283                 }
3284         
3285 #if 0
3286                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3287                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3288                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3289                 pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3290                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3291 #endif
3292
3293                 pic16_emitpcodeNULLop(POC_RETFIE);
3294         }
3295         else {
3296                 if (IFFUNC_ISCRITICAL(sym->type))
3297                         pic16_emitcode("setb","ea");
3298         
3299         /* if any registers used */
3300         if (sym->regsUsed) {
3301           int i;
3302                 /* save the registers used */
3303                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3304                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3305                         if (bitVectBitValue(sym->regsUsed,i)) {
3306 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3307 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3308 //                                              pic16_regWithIdx(i)->name);
3309         
3310                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3311                                         &pic16_pc_preinc1,
3312                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3313                         }
3314                 }
3315         }
3316         
3317
3318         /* if debug then send end of function */
3319         if (currFunc) {
3320             _G.debugLine = 1;
3321             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3322                      FileBaseName(ic->filename),currFunc->lastLine,
3323                      ic->level,ic->block); 
3324             if (IS_STATIC(currFunc->etype))         
3325                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3326             else
3327                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3328             _G.debugLine = 0;
3329         }
3330
3331         /* insert code to restore stack frame, if user enabled it
3332          * and function is not main() */
3333          
3334         if(strcmp(sym->name, "main")) {
3335                 if(!options.ommitFramePtr || sym->regsUsed) {
3336                         /* restore stack frame */
3337                         if(STACK_MODEL_LARGE)
3338                                 pic16_emitpcode(POC_MOVFF,
3339                                         pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3340                         pic16_emitpcode(POC_MOVFF,
3341                                         pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3342                 }
3343         }
3344
3345         pic16_emitcode ("return","");
3346         pic16_emitpcodeNULLop(POC_RETURN);
3347
3348         /* Mark the end of a function */
3349         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3350     }
3351
3352 }
3353
3354
3355 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3356 {
3357 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
3358
3359         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3360                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3361                 pic16_emitpcode(POC_MOVWF, dest);
3362         } else {
3363                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3364                         pic16_popGet(AOP(op), offset), dest));
3365         }
3366 }
3367
3368 /*-----------------------------------------------------------------*/
3369 /* genRet - generate code for return statement                     */
3370 /*-----------------------------------------------------------------*/
3371 static void genRet (iCode *ic)
3372 {
3373   int size;
3374   operand *left;
3375
3376         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3377         /* if we have no return value then
3378          * just generate the "ret" */
3379         
3380         if (!IC_LEFT(ic)) 
3381                 goto jumpret;       
3382     
3383         /* we have something to return then
3384          * move the return value into place */
3385         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3386         size = AOP_SIZE(IC_LEFT(ic));
3387
3388         if(size <= 4) {
3389                 if(size>3) {
3390                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3391 //                      pic16_emitpcode(POC_MOVFF,
3392 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3393                 }
3394                 if(size>2) {
3395                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3396 //                      pic16_emitpcode(POC_MOVFF,
3397 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3398                 }
3399                 if(size>1) {
3400                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3401 //                      pic16_emitpcode(POC_MOVFF,
3402 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3403                 }
3404
3405                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));
3406
3407 //              pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));
3408 //              pic16_emitpcode(POC_MOVFF,
3409 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3410
3411         } else {
3412                 /* >32-bits, setup stack and FSR0 */
3413                 while (size--) {
3414 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3415 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3416
3417                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3418
3419 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3420                         GpsuedoStkPtr++;
3421                 }
3422                         
3423                 /* setup FSR0 */
3424                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3425                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3426
3427                 if(STACK_MODEL_LARGE) {
3428                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3429                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3430                 } else {
3431                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3432                 }
3433         }
3434                                 
3435 #if 0
3436         /* old code, left here for reference -- VR */    
3437         while (size--) {
3438           char *l ;
3439
3440                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3441                         /* #NOCHANGE */
3442                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3443                         pic16_emitpcomment("push %s",l);
3444                         pushed++;
3445                 } else {
3446                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3447                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3448                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3449                         
3450                         if (strcmp(fReturn[offset],l)) {
3451                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3452                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3453                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3454                                 } else {
3455                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3456                                 }
3457                                 
3458                                 if(size) {
3459                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3460                                 }
3461                                 offset++;
3462                         }
3463                 }
3464         }    
3465
3466         if (pushed) {
3467                 while(pushed) {
3468                         pushed--;
3469                         if (strcmp(fReturn[pushed],"a"))
3470                                 pic16_emitcode("pop",fReturn[pushed]);
3471                         else
3472                                 pic16_emitcode("pop","acc");
3473                 }
3474         }
3475 #endif
3476
3477
3478         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3479     
3480 jumpret:
3481         /* generate a jump to the return label
3482          * if the next is not the return statement */
3483         if (!(ic->next && ic->next->op == LABEL
3484                 && IC_LABEL(ic->next) == returnLabel)) {
3485         
3486                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3487                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3488         }
3489 }
3490
3491 /*-----------------------------------------------------------------*/
3492 /* genLabel - generates a label                                    */
3493 /*-----------------------------------------------------------------*/
3494 static void genLabel (iCode *ic)
3495 {
3496     /* special case never generate */
3497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3498     if (IC_LABEL(ic) == entryLabel)
3499         return ;
3500
3501     pic16_emitpLabel(IC_LABEL(ic)->key);
3502     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3503 }
3504
3505 /*-----------------------------------------------------------------*/
3506 /* genGoto - generates a goto                                      */
3507 /*-----------------------------------------------------------------*/
3508 //tsd
3509 static void genGoto (iCode *ic)
3510 {
3511   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3512   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3513 }
3514
3515
3516 /*-----------------------------------------------------------------*/
3517 /* genMultbits :- multiplication of bits                           */
3518 /*-----------------------------------------------------------------*/
3519 static void genMultbits (operand *left, 
3520                          operand *right, 
3521                          operand *result)
3522 {
3523   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3524
3525   if(!pic16_sameRegs(AOP(result),AOP(right)))
3526     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3527
3528   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3529   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3530   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3531
3532 }
3533
3534
3535 /*-----------------------------------------------------------------*/
3536 /* genMultOneByte : 8 bit multiplication & division                */
3537 /*-----------------------------------------------------------------*/
3538 static void genMultOneByte (operand *left,
3539                             operand *right,
3540                             operand *result)
3541 {
3542   sym_link *opetype = operandType(result);
3543
3544   // symbol *lbl ;
3545   int size,offset;
3546
3547   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3548   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3549   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3550
3551   /* (if two literals, the value is computed before) */
3552   /* if one literal, literal on the right */
3553   if (AOP_TYPE(left) == AOP_LIT){
3554     operand *t = right;
3555     right = left;
3556     left = t;
3557   }
3558
3559   size = AOP_SIZE(result);
3560   if(size == 1) {
3561
3562     if (AOP_TYPE(right) == AOP_LIT){
3563       pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3564                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3565                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3566                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3567     } else {
3568       pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3569                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3570                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3571                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3572     }
3573     pic16_genMult8X8_8 (left, right,result);
3574   } else {  // (size > 1)
3575
3576     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3577                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3578                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3579                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3580
3581     if (SPEC_USIGN(opetype)){
3582       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3583       pic16_genUMult8X8_16 (left, right, result, NULL);
3584
3585       if (size > 2) {
3586         /* for filling the MSBs */
3587         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3588         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3589       }
3590     }
3591     else{
3592       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3593
3594       pic16_emitcode("mov","a,b");
3595
3596       /* adjust the MSB if left or right neg */
3597
3598       /* if one literal */
3599       if (AOP_TYPE(right) == AOP_LIT){
3600         pic16_emitcode("multiply ","right is a lit");
3601         /* AND literal negative */
3602         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3603           /* adjust MSB (c==0 after mul) */
3604           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3605         }
3606       }
3607       else{
3608         pic16_genSMult8X8_16 (left, right, result, NULL);
3609       }
3610
3611       if(size > 2){
3612         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3613         /* get the sign */
3614         pic16_emitcode("rlc","a");
3615         pic16_emitcode("subb","a,acc");
3616       }
3617     }
3618
3619     size -= 2;   
3620     offset = 2;
3621     if (size > 0)
3622       while (size--)
3623         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3624     //pic16_aopPut(AOP(result),"a",offset++);
3625   }
3626 }
3627
3628 /*-----------------------------------------------------------------*/
3629 /* genMult - generates code for multiplication                     */
3630 /*-----------------------------------------------------------------*/
3631 static void genMult (iCode *ic)
3632 {
3633     operand *left = IC_LEFT(ic);
3634     operand *right = IC_RIGHT(ic);
3635     operand *result= IC_RESULT(ic);   
3636
3637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3638     /* assign the amsops */
3639     pic16_aopOp (left,ic,FALSE);
3640     pic16_aopOp (right,ic,FALSE);
3641     pic16_aopOp (result,ic,TRUE);
3642
3643   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3644
3645     /* special cases first */
3646     /* both are bits */
3647     if (AOP_TYPE(left) == AOP_CRY &&
3648         AOP_TYPE(right)== AOP_CRY) {
3649         genMultbits(left,right,result);
3650         goto release ;
3651     }
3652
3653     /* if both are of size == 1 */
3654     if (AOP_SIZE(left) == 1 &&
3655         AOP_SIZE(right) == 1 ) {
3656         genMultOneByte(left,right,result);
3657         goto release ;
3658     }
3659
3660     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3661
3662     /* should have been converted to function call */
3663         assert(0) ;
3664
3665 release :
3666     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3667     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3668     pic16_freeAsmop(result,NULL,ic,TRUE); 
3669 }
3670
3671 /*-----------------------------------------------------------------*/
3672 /* genDivbits :- division of bits                                  */
3673 /*-----------------------------------------------------------------*/
3674 static void genDivbits (operand *left, 
3675                         operand *right, 
3676                         operand *result)
3677 {
3678
3679     char *l;
3680
3681     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3682     /* the result must be bit */    
3683     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3684     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3685
3686     MOVA(l);    
3687
3688     pic16_emitcode("div","ab");
3689     pic16_emitcode("rrc","a");
3690     pic16_aopPut(AOP(result),"c",0);
3691 }
3692
3693 /*-----------------------------------------------------------------*/
3694 /* genDivOneByte : 8 bit division                                  */
3695 /*-----------------------------------------------------------------*/
3696 static void genDivOneByte (operand *left,
3697                            operand *right,
3698                            operand *result)
3699 {
3700     sym_link *opetype = operandType(result);
3701     char *l ;
3702     symbol *lbl ;
3703     int size,offset;
3704
3705     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3706     size = AOP_SIZE(result) - 1;
3707     offset = 1;
3708     /* signed or unsigned */
3709     if (SPEC_USIGN(opetype)) {
3710         /* unsigned is easy */
3711         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3712         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3713         MOVA(l);        
3714         pic16_emitcode("div","ab");
3715         pic16_aopPut(AOP(result),"a",0);
3716         while (size--)
3717             pic16_aopPut(AOP(result),zero,offset++);
3718         return ;
3719     }
3720
3721     /* signed is a little bit more difficult */
3722
3723     /* save the signs of the operands */
3724     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3725     MOVA(l);    
3726     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3727     pic16_emitcode("push","acc"); /* save it on the stack */
3728
3729     /* now sign adjust for both left & right */
3730     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3731     MOVA(l);       
3732     lbl = newiTempLabel(NULL);
3733     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3734     pic16_emitcode("cpl","a");   
3735     pic16_emitcode("inc","a");
3736     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3737     pic16_emitcode("mov","b,a");
3738
3739     /* sign adjust left side */
3740     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3741     MOVA(l);
3742
3743     lbl = newiTempLabel(NULL);
3744     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3745     pic16_emitcode("cpl","a");
3746     pic16_emitcode("inc","a");
3747     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3748
3749     /* now the division */
3750     pic16_emitcode("div","ab");
3751     /* we are interested in the lower order
3752     only */
3753     pic16_emitcode("mov","b,a");
3754     lbl = newiTempLabel(NULL);
3755     pic16_emitcode("pop","acc");   
3756     /* if there was an over flow we don't 
3757     adjust the sign of the result */
3758     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3759     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3760     CLRC;
3761     pic16_emitcode("clr","a");
3762     pic16_emitcode("subb","a,b");
3763     pic16_emitcode("mov","b,a");
3764     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3765
3766     /* now we are done */
3767     pic16_aopPut(AOP(result),"b",0);
3768     if(size > 0){
3769         pic16_emitcode("mov","c,b.7");
3770         pic16_emitcode("subb","a,acc");   
3771     }
3772     while (size--)
3773         pic16_aopPut(AOP(result),"a",offset++);
3774
3775 }
3776
3777 /*-----------------------------------------------------------------*/
3778 /* genDiv - generates code for division                            */
3779 /*-----------------------------------------------------------------*/
3780 static void genDiv (iCode *ic)
3781 {
3782     operand *left = IC_LEFT(ic);
3783     operand *right = IC_RIGHT(ic);
3784     operand *result= IC_RESULT(ic);   
3785
3786     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3787     /* assign the amsops */
3788     pic16_aopOp (left,ic,FALSE);
3789     pic16_aopOp (right,ic,FALSE);
3790     pic16_aopOp (result,ic,TRUE);
3791
3792     /* special cases first */
3793     /* both are bits */
3794     if (AOP_TYPE(left) == AOP_CRY &&
3795         AOP_TYPE(right)== AOP_CRY) {
3796         genDivbits(left,right,result);
3797         goto release ;
3798     }
3799
3800     /* if both are of size == 1 */
3801     if (AOP_SIZE(left) == 1 &&
3802         AOP_SIZE(right) == 1 ) {
3803         genDivOneByte(left,right,result);
3804         goto release ;
3805     }
3806
3807     /* should have been converted to function call */
3808     assert(0);
3809 release :
3810     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3811     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3812     pic16_freeAsmop(result,NULL,ic,TRUE); 
3813 }
3814
3815 /*-----------------------------------------------------------------*/
3816 /* genModbits :- modulus of bits                                   */
3817 /*-----------------------------------------------------------------*/
3818 static void genModbits (operand *left, 
3819                         operand *right, 
3820                         operand *result)
3821 {
3822
3823     char *l;
3824
3825     /* the result must be bit */    
3826     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3827     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3828
3829     MOVA(l);       
3830
3831     pic16_emitcode("div","ab");
3832     pic16_emitcode("mov","a,b");
3833     pic16_emitcode("rrc","a");
3834     pic16_aopPut(AOP(result),"c",0);
3835 }
3836
3837 /*-----------------------------------------------------------------*/
3838 /* genModOneByte : 8 bit modulus                                   */
3839 /*-----------------------------------------------------------------*/
3840 static void genModOneByte (operand *left,
3841                            operand *right,
3842                            operand *result)
3843 {
3844     sym_link *opetype = operandType(result);
3845     char *l ;
3846     symbol *lbl ;
3847
3848     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3849     /* signed or unsigned */
3850     if (SPEC_USIGN(opetype)) {
3851         /* unsigned is easy */
3852         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3853         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3854         MOVA(l);    
3855         pic16_emitcode("div","ab");
3856         pic16_aopPut(AOP(result),"b",0);
3857         return ;
3858     }
3859
3860     /* signed is a little bit more difficult */
3861
3862     /* save the signs of the operands */
3863     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3864     MOVA(l);
3865
3866     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3867     pic16_emitcode("push","acc"); /* save it on the stack */
3868
3869     /* now sign adjust for both left & right */
3870     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3871     MOVA(l);
3872
3873     lbl = newiTempLabel(NULL);
3874     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3875     pic16_emitcode("cpl","a");   
3876     pic16_emitcode("inc","a");
3877     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3878     pic16_emitcode("mov","b,a"); 
3879
3880     /* sign adjust left side */
3881     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3882     MOVA(l);
3883
3884     lbl = newiTempLabel(NULL);
3885     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3886     pic16_emitcode("cpl","a");   
3887     pic16_emitcode("inc","a");
3888     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3889
3890     /* now the multiplication */
3891     pic16_emitcode("div","ab");
3892     /* we are interested in the lower order
3893     only */
3894     lbl = newiTempLabel(NULL);
3895     pic16_emitcode("pop","acc");   
3896     /* if there was an over flow we don't 
3897     adjust the sign of the result */
3898     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3899     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3900     CLRC ;
3901     pic16_emitcode("clr","a");
3902     pic16_emitcode("subb","a,b");
3903     pic16_emitcode("mov","b,a");
3904     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3905
3906     /* now we are done */
3907     pic16_aopPut(AOP(result),"b",0);
3908
3909 }
3910
3911 /*-----------------------------------------------------------------*/
3912 /* genMod - generates code for division                            */
3913 /*-----------------------------------------------------------------*/
3914 static void genMod (iCode *ic)
3915 {
3916     operand *left = IC_LEFT(ic);
3917     operand *right = IC_RIGHT(ic);
3918     operand *result= IC_RESULT(ic);  
3919
3920     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3921     /* assign the amsops */
3922     pic16_aopOp (left,ic,FALSE);
3923     pic16_aopOp (right,ic,FALSE);
3924     pic16_aopOp (result,ic,TRUE);
3925
3926     /* special cases first */
3927     /* both are bits */
3928     if (AOP_TYPE(left) == AOP_CRY &&
3929         AOP_TYPE(right)== AOP_CRY) {
3930         genModbits(left,right,result);
3931         goto release ;
3932     }
3933
3934     /* if both are of size == 1 */
3935     if (AOP_SIZE(left) == 1 &&
3936         AOP_SIZE(right) == 1 ) {
3937         genModOneByte(left,right,result);
3938         goto release ;
3939     }
3940
3941     /* should have been converted to function call */
3942     assert(0);
3943
3944 release :
3945     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3946     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3947     pic16_freeAsmop(result,NULL,ic,TRUE); 
3948 }
3949
3950 /*-----------------------------------------------------------------*/
3951 /* genIfxJump :- will create a jump depending on the ifx           */
3952 /*-----------------------------------------------------------------*/
3953 /*
3954   note: May need to add parameter to indicate when a variable is in bit space.
3955 */
3956 static void genIfxJump (iCode *ic, char *jval)
3957 {
3958
3959     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3960     /* if true label then we jump if condition
3961     supplied is true */
3962     if ( IC_TRUE(ic) ) {
3963
3964         if(strcmp(jval,"a") == 0)
3965           emitSKPZ;
3966         else if (strcmp(jval,"c") == 0)
3967           emitSKPC;
3968         else {
3969           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3970           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3971         }
3972
3973         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3974         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3975
3976     }
3977     else {
3978         /* false label is present */
3979         if(strcmp(jval,"a") == 0)
3980           emitSKPNZ;
3981         else if (strcmp(jval,"c") == 0)
3982           emitSKPNC;
3983         else {
3984           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3985           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3986         }
3987
3988         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3989         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3990
3991     }
3992
3993
3994     /* mark the icode as generated */
3995     ic->generated = 1;
3996 }
3997
3998 /*-----------------------------------------------------------------*/
3999 /* genSkip                                                         */
4000 /*-----------------------------------------------------------------*/
4001 static void genSkip(iCode *ifx,int status_bit)
4002 {
4003   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4004   if(!ifx)
4005     return;
4006
4007   if ( IC_TRUE(ifx) ) {
4008     switch(status_bit) {
4009     case 'z':
4010       emitSKPNZ;
4011       break;
4012
4013     case 'c':
4014       emitSKPNC;
4015       break;
4016
4017     case 'd':
4018       emitSKPDC;
4019       break;
4020
4021     }
4022
4023     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4024     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4025
4026   } else {
4027
4028     switch(status_bit) {
4029
4030     case 'z':
4031       emitSKPZ;
4032       break;
4033
4034     case 'c':
4035       emitSKPC;
4036       break;
4037
4038     case 'd':
4039       emitSKPDC;
4040       break;
4041     }
4042     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4043     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4044
4045   }
4046
4047 }
4048
4049 /*-----------------------------------------------------------------*/
4050 /* genSkipc                                                        */
4051 /*-----------------------------------------------------------------*/
4052 static void genSkipc(resolvedIfx *rifx)
4053 {
4054   if(!rifx)
4055     return;
4056
4057   if(rifx->condition)
4058     emitSKPC;
4059   else
4060     emitSKPNC;
4061
4062   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4063   rifx->generated = 1;
4064 }
4065
4066 /*-----------------------------------------------------------------*/
4067 /* genSkipz2                                                       */
4068 /*-----------------------------------------------------------------*/
4069 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4070 {
4071   if(!rifx)
4072     return;
4073
4074   if( (rifx->condition ^ invert_condition) & 1)
4075     emitSKPZ;
4076   else
4077     emitSKPNZ;
4078
4079   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4080   rifx->generated = 1;
4081 }
4082
4083 #if 0
4084 /*-----------------------------------------------------------------*/
4085 /* genSkipz                                                        */
4086 /*-----------------------------------------------------------------*/
4087 static void genSkipz(iCode *ifx, int condition)
4088 {
4089   if(!ifx)
4090     return;
4091
4092   if(condition)
4093     emitSKPNZ;
4094   else
4095     emitSKPZ;
4096
4097   if ( IC_TRUE(ifx) )
4098     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4099   else
4100     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4101
4102   if ( IC_TRUE(ifx) )
4103     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4104   else
4105     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4106
4107 }
4108 #endif
4109
4110 /*-----------------------------------------------------------------*/
4111 /* genSkipCond                                                     */
4112 /*-----------------------------------------------------------------*/
4113 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4114 {
4115   if(!rifx)
4116     return;
4117
4118   if(rifx->condition)
4119     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4120   else
4121     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4122
4123
4124   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4125   rifx->generated = 1;
4126 }
4127
4128 #if 0
4129 /*-----------------------------------------------------------------*/
4130 /* genChkZeroes :- greater or less than comparison                 */
4131 /*     For each byte in a literal that is zero, inclusive or the   */
4132 /*     the corresponding byte in the operand with W                */
4133 /*     returns true if any of the bytes are zero                   */
4134 /*-----------------------------------------------------------------*/
4135 static int genChkZeroes(operand *op, int lit,  int size)
4136 {
4137
4138   int i;
4139   int flag =1;
4140
4141   while(size--) {
4142     i = (lit >> (size*8)) & 0xff;
4143
4144     if(i==0) {
4145       if(flag) 
4146         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4147       else
4148         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4149       flag = 0;
4150     }
4151   }
4152
4153   return (flag==0);
4154 }
4155 #endif
4156
4157 /*-----------------------------------------------------------------*/
4158 /* genCmp :- greater or less than comparison                       */
4159 /*-----------------------------------------------------------------*/
4160 static void genCmp (operand *left,operand *right,
4161                     operand *result, iCode *ifx, int sign)
4162 {
4163   int size; //, offset = 0 ;
4164   unsigned long lit = 0L,i = 0;
4165   resolvedIfx rFalseIfx;
4166   //  resolvedIfx rTrueIfx;
4167   symbol *truelbl;
4168   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4169 /*
4170   if(ifx) {
4171     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4172     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4173   }
4174 */
4175
4176   resolveIfx(&rFalseIfx,ifx);
4177   truelbl  = newiTempLabel(NULL);
4178   size = max(AOP_SIZE(left),AOP_SIZE(right));
4179
4180   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4181
4182 #define _swapp
4183
4184   /* if literal is on the right then swap with left */
4185   if ((AOP_TYPE(right) == AOP_LIT)) {
4186     operand *tmp = right ;
4187     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4188     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4189 #ifdef _swapp
4190
4191     lit = (lit - 1) & mask;
4192     right = left;
4193     left = tmp;
4194     rFalseIfx.condition ^= 1;
4195 #endif
4196
4197   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4198     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4199   }
4200
4201
4202   //if(IC_TRUE(ifx) == NULL)
4203   /* if left & right are bit variables */
4204   if (AOP_TYPE(left) == AOP_CRY &&
4205       AOP_TYPE(right) == AOP_CRY ) {
4206     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4207     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4208   } else {
4209     /* subtract right from left if at the
4210        end the carry flag is set then we know that
4211        left is greater than right */
4212
4213     //    {
4214
4215     symbol *lbl  = newiTempLabel(NULL);
4216
4217 #ifndef _swapp
4218     if(AOP_TYPE(right) == AOP_LIT) {
4219
4220       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4221
4222       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4223
4224       /* special cases */
4225
4226       if(lit == 0) {
4227
4228         if(sign != 0) 
4229           genSkipCond(&rFalseIfx,left,size-1,7);
4230         else 
4231           /* no need to compare to 0...*/
4232           /* NOTE: this is a de-generate compare that most certainly 
4233            *       creates some dead code. */
4234           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4235
4236         if(ifx) ifx->generated = 1;
4237         return;
4238
4239       }
4240       size--;
4241
4242       if(size == 0) {
4243         //i = (lit >> (size*8)) & 0xff;
4244         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4245         
4246         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4247
4248         i = ((0-lit) & 0xff);
4249         if(sign) {
4250           if( i == 0x81) { 
4251             /* lit is 0x7f, all signed chars are less than
4252              * this except for 0x7f itself */
4253             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4254             genSkipz2(&rFalseIfx,0);
4255           } else {
4256             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4257             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4258             genSkipc(&rFalseIfx);
4259           }
4260
4261         } else {
4262           if(lit == 1) {
4263             genSkipz2(&rFalseIfx,1);
4264           } else {
4265             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4266             genSkipc(&rFalseIfx);
4267           }
4268         }
4269
4270         if(ifx) ifx->generated = 1;
4271         return;
4272       }
4273
4274       /* chars are out of the way. now do ints and longs */
4275
4276
4277       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4278         
4279       /* special cases */
4280
4281       if(sign) {
4282
4283         if(lit == 0) {
4284           genSkipCond(&rFalseIfx,left,size,7);
4285           if(ifx) ifx->generated = 1;
4286           return;
4287         }
4288
4289         if(lit <0x100) {
4290           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4291
4292           //rFalseIfx.condition ^= 1;
4293           //genSkipCond(&rFalseIfx,left,size,7);
4294           //rFalseIfx.condition ^= 1;
4295
4296           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4297           if(rFalseIfx.condition)
4298             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4299           else
4300             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4301
4302           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4303           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4304           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4305
4306           while(size > 1)
4307             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4308
4309           if(rFalseIfx.condition) {
4310             emitSKPZ;
4311             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4312
4313           } else {
4314             emitSKPNZ;
4315           }
4316
4317           genSkipc(&rFalseIfx);
4318           pic16_emitpLabel(truelbl->key);
4319           if(ifx) ifx->generated = 1;
4320           return;
4321
4322         }
4323
4324         if(size == 1) {
4325
4326           if( (lit & 0xff) == 0) {
4327             /* lower byte is zero */
4328             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4329             i = ((lit >> 8) & 0xff) ^0x80;
4330             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4331             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4332             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4333             genSkipc(&rFalseIfx);
4334
4335
4336             if(ifx) ifx->generated = 1;
4337             return;
4338
4339           }
4340         } else {
4341           /* Special cases for signed longs */
4342           if( (lit & 0xffffff) == 0) {
4343             /* lower byte is zero */
4344             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4345             i = ((lit >> 8*3) & 0xff) ^0x80;
4346             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4347             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4348             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4349             genSkipc(&rFalseIfx);
4350
4351
4352             if(ifx) ifx->generated = 1;
4353             return;
4354
4355           }
4356
4357         }
4358
4359
4360         if(lit & (0x80 << (size*8))) {
4361           /* lit is negative */
4362           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4363
4364           //genSkipCond(&rFalseIfx,left,size,7);
4365
4366           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4367
4368           if(rFalseIfx.condition)
4369             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4370           else
4371             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4372
4373
4374         } else {
4375           /* lit is positive */
4376           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4377           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4378           if(rFalseIfx.condition)
4379             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4380           else
4381             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4382
4383         }
4384
4385         /*
4386           This works, but is only good for ints.
4387           It also requires a "known zero" register.
4388           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4389           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4390           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4391           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4392           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4393           genSkipc(&rFalseIfx);
4394
4395           pic16_emitpLabel(truelbl->key);
4396           if(ifx) ifx->generated = 1;
4397           return;
4398         **/
4399           
4400         /* There are no more special cases, so perform a general compare */
4401   
4402         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4403         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4404
4405         while(size--) {
4406
4407           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4408           emitSKPNZ;
4409           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4410         }
4411         //rFalseIfx.condition ^= 1;
4412         genSkipc(&rFalseIfx);
4413
4414         pic16_emitpLabel(truelbl->key);
4415
4416         if(ifx) ifx->generated = 1;
4417         return;
4418
4419
4420       }
4421
4422
4423       /* sign is out of the way. So now do an unsigned compare */
4424       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4425
4426
4427       /* General case - compare to an unsigned literal on the right.*/
4428
4429       i = (lit >> (size*8)) & 0xff;
4430       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4431       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4432       while(size--) {
4433         i = (lit >> (size*8)) & 0xff;
4434
4435         if(i) {
4436           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4437           emitSKPNZ;
4438           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4439         } else {
4440           /* this byte of the lit is zero, 
4441            *if it's not the last then OR in the variable */
4442           if(size)
4443             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4444         }
4445       }
4446
4447
4448       pic16_emitpLabel(lbl->key);
4449       //if(emitFinalCheck)
4450       genSkipc(&rFalseIfx);
4451       if(sign)
4452         pic16_emitpLabel(truelbl->key);
4453
4454       if(ifx) ifx->generated = 1;
4455       return;
4456
4457
4458     }
4459 #endif  // _swapp
4460
4461     if(AOP_TYPE(left) == AOP_LIT) {
4462       //symbol *lbl = newiTempLabel(NULL);
4463
4464       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4465
4466
4467       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4468
4469       /* Special cases */
4470       if((lit == 0) && (sign == 0)){
4471
4472         size--;
4473         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4474         while(size) 
4475           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4476
4477         genSkipz2(&rFalseIfx,0);
4478         if(ifx) ifx->generated = 1;
4479         return;
4480       }
4481
4482       if(size==1) {
4483         /* Special cases */
4484         lit &= 0xff;
4485         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4486           /* degenerate compare can never be true */
4487           if(rFalseIfx.condition == 0)
4488             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4489
4490           if(ifx) ifx->generated = 1;
4491           return;
4492         }
4493
4494         if(sign) {
4495           /* signed comparisons to a literal byte */
4496
4497           int lp1 = (lit+1) & 0xff;
4498
4499           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4500           switch (lp1) {
4501           case 0:
4502             rFalseIfx.condition ^= 1;
4503             genSkipCond(&rFalseIfx,right,0,7);
4504             break;
4505           case 0x7f:
4506             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4507             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4508             genSkipz2(&rFalseIfx,1);
4509             break;
4510           default:
4511             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4512             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4513             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4514             rFalseIfx.condition ^= 1;
4515             genSkipc(&rFalseIfx);
4516             break;
4517           }
4518         } else {
4519           /* unsigned comparisons to a literal byte */
4520
4521           switch(lit & 0xff ) {
4522           case 0:
4523             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4524             genSkipz2(&rFalseIfx,0);
4525             break;
4526           case 0x7f:
4527             rFalseIfx.condition ^= 1;
4528             genSkipCond(&rFalseIfx,right,0,7);
4529             break;
4530
4531           default:
4532             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4533             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4534             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4535             rFalseIfx.condition ^= 1;
4536             if (AOP_TYPE(result) == AOP_CRY)
4537               genSkipc(&rFalseIfx);
4538             else {
4539               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4540               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4541             }         
4542             break;
4543           }
4544         }
4545
4546         if(ifx) ifx->generated = 1;
4547         //goto check_carry;
4548         return;
4549
4550       } else {
4551
4552         /* Size is greater than 1 */
4553
4554         if(sign) {
4555           int lp1 = lit+1;
4556
4557           size--;
4558
4559           if(lp1 == 0) {
4560             /* this means lit = 0xffffffff, or -1 */
4561
4562
4563             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4564             rFalseIfx.condition ^= 1;
4565             genSkipCond(&rFalseIfx,right,size,7);
4566             if(ifx) ifx->generated = 1;
4567             return;
4568           }
4569
4570           if(lit == 0) {
4571             int s = size;
4572
4573             if(rFalseIfx.condition) {
4574               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4575               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4576             }
4577
4578             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4579             while(size--)
4580               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4581
4582
4583             emitSKPZ;
4584             if(rFalseIfx.condition) {
4585               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4586               pic16_emitpLabel(truelbl->key);
4587             }else {
4588               rFalseIfx.condition ^= 1;
4589               genSkipCond(&rFalseIfx,right,s,7);
4590             }
4591
4592             if(ifx) ifx->generated = 1;
4593             return;
4594           }
4595
4596           if((size == 1) &&  (0 == (lp1&0xff))) {
4597             /* lower byte of signed word is zero */
4598             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4599             i = ((lp1 >> 8) & 0xff) ^0x80;
4600             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4601             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4602             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4603             rFalseIfx.condition ^= 1;
4604             genSkipc(&rFalseIfx);
4605
4606
4607             if(ifx) ifx->generated = 1;
4608             return;
4609           }
4610
4611           if(lit & (0x80 << (size*8))) {
4612             /* Lit is less than zero */
4613             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4614             //rFalseIfx.condition ^= 1;
4615             //genSkipCond(&rFalseIfx,left,size,7);
4616             //rFalseIfx.condition ^= 1;
4617             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4618             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4619
4620             if(rFalseIfx.condition)
4621               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4622             else
4623               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4624
4625
4626           } else {
4627             /* Lit is greater than or equal to zero */
4628             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4629             //rFalseIfx.condition ^= 1;
4630             //genSkipCond(&rFalseIfx,right,size,7);
4631             //rFalseIfx.condition ^= 1;
4632
4633             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4634             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4635
4636             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4637             if(rFalseIfx.condition)
4638               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4639             else
4640               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4641
4642           }
4643
4644
4645           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4646           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4647
4648           while(size--) {
4649
4650             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4651             emitSKPNZ;
4652             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4653           }
4654           rFalseIfx.condition ^= 1;
4655           //rFalseIfx.condition = 1;
4656           genSkipc(&rFalseIfx);
4657
4658           pic16_emitpLabel(truelbl->key);
4659
4660           if(ifx) ifx->generated = 1;
4661           return;
4662           // end of if (sign)
4663         } else {
4664
4665           /* compare word or long to an unsigned literal on the right.*/
4666
4667
4668           size--;
4669           if(lit < 0xff) {
4670             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4671             switch (lit) {
4672             case 0:
4673               break; /* handled above */
4674 /*
4675             case 0xff:
4676               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4677               while(size--)
4678                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4679               genSkipz2(&rFalseIfx,0);
4680               break;
4681 */
4682             default:
4683               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4684               while(--size)
4685                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4686
4687               emitSKPZ;
4688               if(rFalseIfx.condition)
4689                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4690               else
4691                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4692
4693
4694               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4695               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4696
4697               rFalseIfx.condition ^= 1;
4698               genSkipc(&rFalseIfx);
4699             }
4700
4701             pic16_emitpLabel(truelbl->key);
4702
4703             if(ifx) ifx->generated = 1;
4704             return;
4705           }
4706
4707
4708           lit++;
4709           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4710           i = (lit >> (size*8)) & 0xff;
4711
4712           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4713           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4714
4715           while(size--) {
4716             i = (lit >> (size*8)) & 0xff;
4717
4718             if(i) {
4719               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4720               emitSKPNZ;
4721               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4722             } else {
4723               /* this byte of the lit is zero, 
4724                *if it's not the last then OR in the variable */
4725               if(size)
4726                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4727             }
4728           }
4729
4730
4731           pic16_emitpLabel(lbl->key);
4732
4733           rFalseIfx.condition ^= 1;
4734           genSkipc(&rFalseIfx);
4735         }
4736
4737         if(sign)
4738           pic16_emitpLabel(truelbl->key);
4739         if(ifx) ifx->generated = 1;
4740         return;
4741       }
4742     }
4743     /* Compare two variables */
4744
4745     DEBUGpic16_emitcode(";sign","%d",sign);
4746
4747     size--;
4748     if(sign) {
4749       /* Sigh. thus sucks... */
4750       if(size) {
4751         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4752         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4753         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4754         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4755         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4756         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4757       } else {
4758         /* Signed char comparison */
4759         /* Special thanks to Nikolai Golovchenko for this snippet */
4760         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4761         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4762         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4763         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4764         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4765         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4766
4767         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4768         genSkipc(&rFalseIfx);
4769           
4770         if(ifx) ifx->generated = 1;
4771         return;
4772       }
4773
4774     } else {
4775
4776       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4777       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4778     }
4779
4780
4781     /* The rest of the bytes of a multi-byte compare */
4782     while (size) {
4783
4784       emitSKPZ;
4785       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4786       size--;
4787
4788       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4789       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4790
4791
4792     }
4793
4794     pic16_emitpLabel(lbl->key);
4795
4796     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4797     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4798         (AOP_TYPE(result) == AOP_REG)) {
4799       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4800       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4801     } else {
4802       genSkipc(&rFalseIfx);
4803     }         
4804     //genSkipc(&rFalseIfx);
4805     if(ifx) ifx->generated = 1;
4806
4807     return;
4808
4809   }
4810
4811   // check_carry:
4812   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4814     pic16_outBitC(result);
4815   } else {
4816     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4817     /* if the result is used in the next
4818        ifx conditional branch then generate
4819        code a little differently */
4820     if (ifx )
4821       genIfxJump (ifx,"c");
4822     else
4823       pic16_outBitC(result);
4824     /* leave the result in acc */
4825   }
4826
4827 }
4828
4829 /*-----------------------------------------------------------------*/
4830 /* genCmpGt :- greater than comparison                             */
4831 /*-----------------------------------------------------------------*/
4832 static void genCmpGt (iCode *ic, iCode *ifx)
4833 {
4834     operand *left, *right, *result;
4835     sym_link *letype , *retype;
4836     int sign ;
4837
4838     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4839     left = IC_LEFT(ic);
4840     right= IC_RIGHT(ic);
4841     result = IC_RESULT(ic);
4842
4843     letype = getSpec(operandType(left));
4844     retype =getSpec(operandType(right));
4845     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4846     /* assign the amsops */
4847     pic16_aopOp (left,ic,FALSE);
4848     pic16_aopOp (right,ic,FALSE);
4849     pic16_aopOp (result,ic,TRUE);
4850
4851     genCmp(right, left, result, ifx, sign);
4852
4853     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4854     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4855     pic16_freeAsmop(result,NULL,ic,TRUE); 
4856 }
4857
4858 /*-----------------------------------------------------------------*/
4859 /* genCmpLt - less than comparisons                                */
4860 /*-----------------------------------------------------------------*/
4861 static void genCmpLt (iCode *ic, iCode *ifx)
4862 {
4863     operand *left, *right, *result;
4864     sym_link *letype , *retype;
4865     int sign ;
4866
4867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4868     left = IC_LEFT(ic);
4869     right= IC_RIGHT(ic);
4870     result = IC_RESULT(ic);
4871
4872     letype = getSpec(operandType(left));
4873     retype =getSpec(operandType(right));
4874     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4875
4876     /* assign the amsops */
4877     pic16_aopOp (left,ic,FALSE);
4878     pic16_aopOp (right,ic,FALSE);
4879     pic16_aopOp (result,ic,TRUE);
4880
4881     genCmp(left, right, result, ifx, sign);
4882
4883     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4884     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4885     pic16_freeAsmop(result,NULL,ic,TRUE); 
4886 }
4887
4888 /*-----------------------------------------------------------------*/
4889 /* genc16bit2lit - compare a 16 bit value to a literal             */
4890 /*-----------------------------------------------------------------*/
4891 static void genc16bit2lit(operand *op, int lit, int offset)
4892 {
4893   int i;
4894
4895   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4896   if( (lit&0xff) == 0) 
4897     i=1;
4898   else
4899     i=0;
4900
4901   switch( BYTEofLONG(lit,i)) { 
4902   case 0:
4903     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4904     break;
4905   case 1:
4906     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4907     break;
4908   case 0xff:
4909     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4910     break;
4911   default:
4912     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4913     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4914   }
4915
4916   i ^= 1;
4917
4918   switch( BYTEofLONG(lit,i)) { 
4919   case 0:
4920     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4921     break;
4922   case 1:
4923     emitSKPNZ;
4924     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4925     break;
4926   case 0xff:
4927     emitSKPNZ;
4928     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4929     break;
4930   default:
4931     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4932     emitSKPNZ;
4933     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4934
4935   }
4936
4937 }
4938
4939 /*-----------------------------------------------------------------*/
4940 /* gencjneshort - compare and jump if not equal                    */
4941 /*-----------------------------------------------------------------*/
4942 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4943 {
4944   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4945   int offset = 0;
4946   int res_offset = 0;  /* the result may be a different size then left or right */
4947   int res_size = AOP_SIZE(result);
4948   resolvedIfx rIfx;
4949   symbol *lbl;
4950
4951   unsigned long lit = 0L;
4952   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4953   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4954   if(result)
4955     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4956   resolveIfx(&rIfx,ifx);
4957   lbl =  newiTempLabel(NULL);
4958
4959
4960   /* if the left side is a literal or 
4961      if the right is in a pointer register and left 
4962      is not */
4963   if ((AOP_TYPE(left) == AOP_LIT) || 
4964       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4965     operand *t = right;
4966     right = left;
4967     left = t;
4968   }
4969   if(AOP_TYPE(right) == AOP_LIT)
4970     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4971
4972   /* if the right side is a literal then anything goes */
4973   if (AOP_TYPE(right) == AOP_LIT &&
4974       AOP_TYPE(left) != AOP_DIR ) {
4975     switch(size) {
4976     case 2:
4977       genc16bit2lit(left, lit, 0);
4978       emitSKPNZ;
4979       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4980       break;
4981     default:
4982       while (size--) {
4983         if(lit & 0xff) {
4984           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4985           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4986         } else {
4987           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4988         }
4989
4990         emitSKPNZ;
4991         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4992         offset++;
4993         if(res_offset < res_size-1)
4994           res_offset++;
4995         lit >>= 8;
4996       }
4997       break;
4998     }
4999   }
5000
5001   /* if the right side is in a register or in direct space or
5002      if the left is a pointer register & right is not */    
5003   else if (AOP_TYPE(right) == AOP_REG ||
5004            AOP_TYPE(right) == AOP_DIR || 
5005            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5006            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5007     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5008     int lbl_key = lbl->key;
5009
5010     if(result) {
5011       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5012       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5013     }else {
5014       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5015       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5016               __FUNCTION__,__LINE__);
5017       return;
5018     }
5019
5020 /*     switch(size) { */
5021 /*     case 2: */
5022 /*       genc16bit2lit(left, lit, 0); */
5023 /*       emitSKPNZ; */
5024 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5025 /*       break; */
5026 /*     default: */
5027     while (size--) {
5028       int emit_skip=1;
5029       if((AOP_TYPE(left) == AOP_DIR) && 
5030          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5031
5032         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5033         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5034
5035       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5036             
5037         switch (lit & 0xff) {
5038         case 0:
5039           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5040           break;
5041         case 1:
5042           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5043           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5044           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5045           emit_skip=0;
5046           break;
5047         case 0xff:
5048           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5049           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5050           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5051           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5052           emit_skip=0;
5053           break;
5054         default:
5055           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5056           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5057         }
5058         lit >>= 8;
5059
5060       } else {
5061         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5062       }
5063       if(emit_skip) {
5064         if(AOP_TYPE(result) == AOP_CRY) {
5065           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5066           if(rIfx.condition)
5067             emitSKPNZ;
5068           else
5069             emitSKPZ;
5070           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5071         } else {
5072           /* fix me. probably need to check result size too */
5073           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5074           if(rIfx.condition)
5075             emitSKPZ;
5076           else
5077             emitSKPNZ;
5078           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5079           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5080         }
5081         if(ifx)
5082           ifx->generated=1;
5083       }
5084       emit_skip++;
5085       offset++;
5086       if(res_offset < res_size-1)
5087         res_offset++;
5088     }
5089 /*       break; */
5090 /*     } */
5091   } else if(AOP_TYPE(right) == AOP_REG &&
5092             AOP_TYPE(left) != AOP_DIR){
5093
5094     while(size--) {
5095       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5096       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5097       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5098       if(rIfx.condition)
5099         emitSKPNZ;
5100       else
5101         emitSKPZ;
5102       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5103       offset++;
5104       if(res_offset < res_size-1)
5105         res_offset++;
5106     }
5107       
5108   }else{
5109     /* right is a pointer reg need both a & b */
5110     while(size--) {
5111       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5112       if(strcmp(l,"b"))
5113         pic16_emitcode("mov","b,%s",l);
5114       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5115       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5116       offset++;
5117     }
5118   }
5119
5120   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5121   if(!rIfx.condition)
5122     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5123
5124   pic16_emitpLabel(lbl->key);
5125
5126   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5127
5128   if(ifx)
5129     ifx->generated = 1;
5130 }
5131
5132 #if 0
5133 /*-----------------------------------------------------------------*/
5134 /* gencjne - compare and jump if not equal                         */
5135 /*-----------------------------------------------------------------*/
5136 static void gencjne(operand *left, operand *right, iCode *ifx)
5137 {
5138     symbol *tlbl  = newiTempLabel(NULL);
5139
5140     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5141     gencjneshort(left, right, lbl);
5142
5143     pic16_emitcode("mov","a,%s",one);
5144     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5145     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5146     pic16_emitcode("clr","a");
5147     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5148
5149     pic16_emitpLabel(lbl->key);
5150     pic16_emitpLabel(tlbl->key);
5151
5152 }
5153 #endif
5154
5155 /*-----------------------------------------------------------------*/
5156 /* genCmpEq - generates code for equal to                          */
5157 /*-----------------------------------------------------------------*/
5158 static void genCmpEq (iCode *ic, iCode *ifx)
5159 {
5160     operand *left, *right, *result;
5161     unsigned long lit = 0L;
5162     int size,offset=0;
5163     symbol *falselbl  = newiTempLabel(NULL);
5164
5165
5166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5167
5168     if(ifx)
5169       DEBUGpic16_emitcode ("; ifx is non-null","");
5170     else
5171       DEBUGpic16_emitcode ("; ifx is null","");
5172
5173     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5174     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5175     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5176
5177     size = max(AOP_SIZE(left),AOP_SIZE(right));
5178
5179     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5180
5181     /* if literal, literal on the right or 
5182     if the right is in a pointer register and left 
5183     is not */
5184     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5185         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5186       operand *tmp = right ;
5187       right = left;
5188       left = tmp;
5189     }
5190
5191
5192     if(ifx && !AOP_SIZE(result)){
5193         symbol *tlbl;
5194         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5195         /* if they are both bit variables */
5196         if (AOP_TYPE(left) == AOP_CRY &&
5197             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5198                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5199             if(AOP_TYPE(right) == AOP_LIT){
5200                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5201                 if(lit == 0L){
5202                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5203                     pic16_emitcode("cpl","c");
5204                 } else if(lit == 1L) {
5205                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5206                 } else {
5207                     pic16_emitcode("clr","c");
5208                 }
5209                 /* AOP_TYPE(right) == AOP_CRY */
5210             } else {
5211                 symbol *lbl = newiTempLabel(NULL);
5212                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5213                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5214                 pic16_emitcode("cpl","c");
5215                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5216             }
5217             /* if true label then we jump if condition
5218             supplied is true */
5219             tlbl = newiTempLabel(NULL);
5220             if ( IC_TRUE(ifx) ) {
5221                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5222                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5223             } else {
5224                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5225                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5226             }
5227             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5228
5229                 {
5230                 /* left and right are both bit variables, result is carry */
5231                         resolvedIfx rIfx;
5232               
5233                         resolveIfx(&rIfx,ifx);
5234
5235                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5236                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5237                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5238                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5239                         genSkipz2(&rIfx,0);
5240                 }
5241         } else {
5242
5243                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5244
5245                         /* They're not both bit variables. Is the right a literal? */
5246                         if(AOP_TYPE(right) == AOP_LIT) {
5247                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5248             
5249                         switch(size) {
5250
5251                                 case 1:
5252                                         switch(lit & 0xff) {
5253                                                 case 1:
5254                                                                 if ( IC_TRUE(ifx) ) {
5255                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5256                                                                         emitSKPNZ;
5257                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5258                                                                 } else {
5259                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5260                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5261                                                                 }
5262                                                                 break;
5263                                                 case 0xff:
5264                                                                 if ( IC_TRUE(ifx) ) {
5265                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5266                                                                         emitSKPNZ;
5267                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5268                                                                 } else {
5269                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5270                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5271                                                                 }
5272                                                                 break;
5273                                                 default:
5274                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5275                                                                 if(lit)
5276                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5277                                                                 genSkip(ifx,'z');
5278                                         } // switch lit
5279
5280
5281                                         /* end of size == 1 */
5282                                         break;
5283               
5284                                 case 2:
5285                                         genc16bit2lit(left,lit,offset);
5286                                         genSkip(ifx,'z');
5287                                         break;
5288                                         /* end of size == 2 */
5289
5290                                 default:
5291                                         /* size is 4 */
5292                                         if(lit==0) {
5293                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5294                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5295                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5296                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5297                                                 genSkip(ifx,'z');
5298                                         } else {
5299                                                 /* search for patterns that can be optimized */
5300
5301                                                 genc16bit2lit(left,lit,0);
5302                                                 lit >>= 16;
5303                                                 if(lit) {
5304                                                                 if(IC_TRUE(ifx))
5305                                                                 emitSKPZ; // if hi word unequal
5306                                                                 else
5307                                                                 emitSKPNZ; // if hi word equal
5308                                                                 // fail early
5309                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5310                                                         genc16bit2lit(left,lit,2);
5311                                                         genSkip(ifx,'z');
5312                                                 } else {
5313                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5314                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5315                                                         genSkip(ifx,'z');
5316                                                 }
5317                                         }
5318                                                 pic16_emitpLabel(falselbl->key);
5319                                                 break;
5320
5321                         } // switch size
5322           
5323                         ifx->generated = 1;
5324                         goto release ;
5325             
5326
5327           } else if(AOP_TYPE(right) == AOP_CRY ) {
5328             /* we know the left is not a bit, but that the right is */
5329             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5330             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5331                       pic16_popGet(AOP(right),offset));
5332             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5333
5334             /* if the two are equal, then W will be 0 and the Z bit is set
5335              * we could test Z now, or go ahead and check the high order bytes if
5336              * the variable we're comparing is larger than a byte. */
5337
5338             while(--size)
5339               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5340
5341             if ( IC_TRUE(ifx) ) {
5342               emitSKPNZ;
5343               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5344               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5345             } else {
5346               emitSKPZ;
5347               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5348               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5349             }
5350
5351           } else {
5352             /* They're both variables that are larger than bits */
5353             int s = size;
5354
5355             tlbl = newiTempLabel(NULL);
5356
5357             while(size--) {
5358               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5359               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5360
5361               if ( IC_TRUE(ifx) ) {
5362                 if(size) {
5363                   emitSKPZ;
5364                 
5365                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5366
5367                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5368                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5369                 } else {
5370                   emitSKPNZ;
5371
5372                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5373
5374
5375                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5376                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5377                 }
5378               } else {
5379                 emitSKPZ;
5380
5381                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5382
5383                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5384                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5385               }
5386               offset++;
5387             }
5388             if(s>1 && IC_TRUE(ifx)) {
5389               pic16_emitpLabel(tlbl->key);
5390               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5391             }
5392           }
5393         }
5394         /* mark the icode as generated */
5395         ifx->generated = 1;
5396         goto release ;
5397     }
5398
5399     /* if they are both bit variables */
5400     if (AOP_TYPE(left) == AOP_CRY &&
5401         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5402         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5403         if(AOP_TYPE(right) == AOP_LIT){
5404             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5405             if(lit == 0L){
5406                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5407                 pic16_emitcode("cpl","c");
5408             } else if(lit == 1L) {
5409                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5410             } else {
5411                 pic16_emitcode("clr","c");
5412             }
5413             /* AOP_TYPE(right) == AOP_CRY */
5414         } else {
5415             symbol *lbl = newiTempLabel(NULL);
5416             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5417             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5418             pic16_emitcode("cpl","c");
5419             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5420         }
5421         /* c = 1 if egal */
5422         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5423             pic16_outBitC(result);
5424             goto release ;
5425         }
5426         if (ifx) {
5427             genIfxJump (ifx,"c");
5428             goto release ;
5429         }
5430         /* if the result is used in an arithmetic operation
5431         then put the result in place */
5432         pic16_outBitC(result);
5433     } else {
5434       
5435       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5436       gencjne(left,right,result,ifx);
5437 /*
5438       if(ifx) 
5439         gencjne(left,right,newiTempLabel(NULL));
5440       else {
5441         if(IC_TRUE(ifx)->key)
5442           gencjne(left,right,IC_TRUE(ifx)->key);
5443         else
5444           gencjne(left,right,IC_FALSE(ifx)->key);
5445         ifx->generated = 1;
5446         goto release ;
5447       }
5448       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5449         pic16_aopPut(AOP(result),"a",0);
5450         goto release ;
5451       }
5452
5453       if (ifx) {
5454         genIfxJump (ifx,"a");
5455         goto release ;
5456       }
5457 */
5458       /* if the result is used in an arithmetic operation
5459          then put the result in place */
5460 /*
5461       if (AOP_TYPE(result) != AOP_CRY) 
5462         pic16_outAcc(result);
5463 */
5464       /* leave the result in acc */
5465     }
5466
5467 release:
5468     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5469     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5470     pic16_freeAsmop(result,NULL,ic,TRUE);
5471 }
5472
5473 /*-----------------------------------------------------------------*/
5474 /* ifxForOp - returns the icode containing the ifx for operand     */
5475 /*-----------------------------------------------------------------*/
5476 static iCode *ifxForOp ( operand *op, iCode *ic )
5477 {
5478     /* if true symbol then needs to be assigned */
5479     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5480     if (IS_TRUE_SYMOP(op))
5481         return NULL ;
5482
5483     /* if this has register type condition and
5484     the next instruction is ifx with the same operand
5485     and live to of the operand is upto the ifx only then */
5486     if (ic->next &&
5487         ic->next->op == IFX &&
5488         IC_COND(ic->next)->key == op->key &&
5489         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5490         return ic->next;
5491
5492     if (ic->next &&
5493         ic->next->op == IFX &&
5494         IC_COND(ic->next)->key == op->key) {
5495       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5496       return ic->next;
5497     }
5498
5499     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5500     if (ic->next &&
5501         ic->next->op == IFX)
5502       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5503
5504     if (ic->next &&
5505         ic->next->op == IFX &&
5506         IC_COND(ic->next)->key == op->key) {
5507       DEBUGpic16_emitcode ("; "," key is okay");
5508       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5509                            OP_SYMBOL(op)->liveTo,
5510                            ic->next->seq);
5511     }
5512
5513
5514     return NULL;
5515 }
5516 /*-----------------------------------------------------------------*/
5517 /* genAndOp - for && operation                                     */
5518 /*-----------------------------------------------------------------*/
5519 static void genAndOp (iCode *ic)
5520 {
5521     operand *left,*right, *result;
5522 /*     symbol *tlbl; */
5523
5524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5525     /* note here that && operations that are in an
5526     if statement are taken away by backPatchLabels
5527     only those used in arthmetic operations remain */
5528     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5529     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5530     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5531
5532     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5533
5534     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5535     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5536     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5537
5538     /* if both are bit variables */
5539 /*     if (AOP_TYPE(left) == AOP_CRY && */
5540 /*         AOP_TYPE(right) == AOP_CRY ) { */
5541 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5542 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5543 /*         pic16_outBitC(result); */
5544 /*     } else { */
5545 /*         tlbl = newiTempLabel(NULL); */
5546 /*         pic16_toBoolean(left);     */
5547 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5548 /*         pic16_toBoolean(right); */
5549 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5550 /*         pic16_outBitAcc(result); */
5551 /*     } */
5552
5553     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5554     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5555     pic16_freeAsmop(result,NULL,ic,TRUE);
5556 }
5557
5558
5559 /*-----------------------------------------------------------------*/
5560 /* genOrOp - for || operation                                      */
5561 /*-----------------------------------------------------------------*/
5562 /*
5563   tsd pic port -
5564   modified this code, but it doesn't appear to ever get called
5565 */
5566
5567 static void genOrOp (iCode *ic)
5568 {
5569     operand *left,*right, *result;
5570     symbol *tlbl;
5571
5572     /* note here that || operations that are in an
5573     if statement are taken away by backPatchLabels
5574     only those used in arthmetic operations remain */
5575     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5576     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5577     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5578     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5579
5580     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5581
5582     /* if both are bit variables */
5583     if (AOP_TYPE(left) == AOP_CRY &&
5584         AOP_TYPE(right) == AOP_CRY ) {
5585       pic16_emitcode("clrc","");
5586       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5587                AOP(left)->aopu.aop_dir,
5588                AOP(left)->aopu.aop_dir);
5589       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5590                AOP(right)->aopu.aop_dir,
5591                AOP(right)->aopu.aop_dir);
5592       pic16_emitcode("setc","");
5593
5594     } else {
5595         tlbl = newiTempLabel(NULL);
5596         pic16_toBoolean(left);
5597         emitSKPZ;
5598         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5599         pic16_toBoolean(right);
5600         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5601
5602         pic16_outBitAcc(result);
5603     }
5604
5605     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5606     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5607     pic16_freeAsmop(result,NULL,ic,TRUE);            
5608 }
5609
5610 /*-----------------------------------------------------------------*/
5611 /* isLiteralBit - test if lit == 2^n                               */
5612 /*-----------------------------------------------------------------*/
5613 static int isLiteralBit(unsigned long lit)
5614 {
5615     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5616     0x100L,0x200L,0x400L,0x800L,
5617     0x1000L,0x2000L,0x4000L,0x8000L,
5618     0x10000L,0x20000L,0x40000L,0x80000L,
5619     0x100000L,0x200000L,0x400000L,0x800000L,
5620     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5621     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5622     int idx;
5623     
5624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5625     for(idx = 0; idx < 32; idx++)
5626         if(lit == pw[idx])
5627             return idx+1;
5628     return 0;
5629 }
5630
5631 /*-----------------------------------------------------------------*/
5632 /* continueIfTrue -                                                */
5633 /*-----------------------------------------------------------------*/
5634 static void continueIfTrue (iCode *ic)
5635 {
5636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5637     if(IC_TRUE(ic))
5638         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5639     ic->generated = 1;
5640 }
5641
5642 /*-----------------------------------------------------------------*/
5643 /* jmpIfTrue -                                                     */
5644 /*-----------------------------------------------------------------*/
5645 static void jumpIfTrue (iCode *ic)
5646 {
5647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5648     if(!IC_TRUE(ic))
5649         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5650     ic->generated = 1;
5651 }
5652
5653 /*-----------------------------------------------------------------*/
5654 /* jmpTrueOrFalse -                                                */
5655 /*-----------------------------------------------------------------*/
5656 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5657 {
5658     // ugly but optimized by peephole
5659     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5660     if(IC_TRUE(ic)){
5661         symbol *nlbl = newiTempLabel(NULL);
5662         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5663         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5664         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5665         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5666     }
5667     else{
5668         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5669         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5670     }
5671     ic->generated = 1;
5672 }
5673
5674 /*-----------------------------------------------------------------*/
5675 /* genAnd  - code for and                                          */
5676 /*-----------------------------------------------------------------*/
5677 static void genAnd (iCode *ic, iCode *ifx)
5678 {
5679   operand *left, *right, *result;
5680   int size, offset=0;  
5681   unsigned long lit = 0L;
5682   int bytelit = 0;
5683   resolvedIfx rIfx;
5684
5685
5686   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5687   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5688   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5689   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5690
5691   resolveIfx(&rIfx,ifx);
5692
5693   /* if left is a literal & right is not then exchange them */
5694   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5695       AOP_NEEDSACC(left)) {
5696     operand *tmp = right ;
5697     right = left;
5698     left = tmp;
5699   }
5700
5701   /* if result = right then exchange them */
5702   if(pic16_sameRegs(AOP(result),AOP(right))){
5703     operand *tmp = right ;
5704     right = left;
5705     left = tmp;
5706   }
5707
5708   /* if right is bit then exchange them */
5709   if (AOP_TYPE(right) == AOP_CRY &&
5710       AOP_TYPE(left) != AOP_CRY){
5711     operand *tmp = right ;
5712     right = left;
5713     left = tmp;
5714   }
5715   if(AOP_TYPE(right) == AOP_LIT)
5716     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5717
5718   size = AOP_SIZE(result);
5719
5720   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5721
5722   // if(bit & yy)
5723   // result = bit & yy;
5724   if (AOP_TYPE(left) == AOP_CRY){
5725     // c = bit & literal;
5726     if(AOP_TYPE(right) == AOP_LIT){
5727       if(lit & 1) {
5728         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5729           // no change
5730           goto release;
5731         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5732       } else {
5733         // bit(result) = 0;
5734         if(size && (AOP_TYPE(result) == AOP_CRY)){
5735           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5736           goto release;
5737         }
5738         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5739           jumpIfTrue(ifx);
5740           goto release;
5741         }
5742         pic16_emitcode("clr","c");
5743       }
5744     } else {
5745       if (AOP_TYPE(right) == AOP_CRY){
5746         // c = bit & bit;
5747         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5748         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5749       } else {
5750         // c = bit & val;
5751         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5752         // c = lsb
5753         pic16_emitcode("rrc","a");
5754         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5755       }
5756     }
5757     // bit = c
5758     // val = c
5759     if(size)
5760       pic16_outBitC(result);
5761     // if(bit & ...)
5762     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5763       genIfxJump(ifx, "c");           
5764     goto release ;
5765   }
5766
5767   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5768   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5769   if((AOP_TYPE(right) == AOP_LIT) &&
5770      (AOP_TYPE(result) == AOP_CRY) &&
5771      (AOP_TYPE(left) != AOP_CRY)){
5772     int posbit = isLiteralBit(lit);
5773     /* left &  2^n */
5774     if(posbit){
5775       posbit--;
5776       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5777       // bit = left & 2^n
5778       if(size)
5779         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5780       // if(left &  2^n)
5781       else{
5782         if(ifx){
5783 /*
5784           if(IC_TRUE(ifx)) {
5785             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5786             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5787           } else {
5788             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5789             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5790           }
5791 */
5792           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5793                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5794           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5795           
5796           ifx->generated = 1;
5797         }
5798         goto release;
5799       }
5800     } else {
5801       symbol *tlbl = newiTempLabel(NULL);
5802       int sizel = AOP_SIZE(left);
5803       if(size)
5804         pic16_emitcode("setb","c");
5805       while(sizel--){
5806         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5807           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5808           // byte ==  2^n ?
5809           if((posbit = isLiteralBit(bytelit)) != 0)
5810             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5811           else{
5812             if(bytelit != 0x0FFL)
5813               pic16_emitcode("anl","a,%s",
5814                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5815             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5816           }
5817         }
5818         offset++;
5819       }
5820       // bit = left & literal
5821       if(size){
5822         pic16_emitcode("clr","c");
5823         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5824       }
5825       // if(left & literal)
5826       else{
5827         if(ifx)
5828           jmpTrueOrFalse(ifx, tlbl);
5829         goto release ;
5830       }
5831     }
5832     pic16_outBitC(result);
5833     goto release ;
5834   }
5835
5836   /* if left is same as result */
5837   if(pic16_sameRegs(AOP(result),AOP(left))){
5838     int know_W = -1;
5839     for(;size--; offset++,lit>>=8) {
5840       if(AOP_TYPE(right) == AOP_LIT){
5841         switch(lit & 0xff) {
5842         case 0x00:
5843           /*  and'ing with 0 has clears the result */
5844 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5845           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5846           break;
5847         case 0xff:
5848           /* and'ing with 0xff is a nop when the result and left are the same */
5849           break;
5850
5851         default:
5852           {
5853             int p = my_powof2( (~lit) & 0xff );
5854             if(p>=0) {
5855               /* only one bit is set in the literal, so use a bcf instruction */
5856 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5857               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5858
5859             } else {
5860               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5861               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5862               if(know_W != (lit&0xff))
5863                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5864               know_W = lit &0xff;
5865               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5866             }
5867           }    
5868         }
5869       } else {
5870         if (AOP_TYPE(left) == AOP_ACC) {
5871           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5872         } else {                    
5873           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5874           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5875
5876         }
5877       }
5878     }
5879
5880   } else {
5881     // left & result in different registers
5882     if(AOP_TYPE(result) == AOP_CRY){
5883       // result = bit
5884       // if(size), result in bit
5885       // if(!size && ifx), conditional oper: if(left & right)
5886       symbol *tlbl = newiTempLabel(NULL);
5887       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5888       if(size)
5889         pic16_emitcode("setb","c");
5890       while(sizer--){
5891         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5892         pic16_emitcode("anl","a,%s",
5893                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5894         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5895         offset++;
5896       }
5897       if(size){
5898         CLRC;
5899         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5900         pic16_outBitC(result);
5901       } else if(ifx)
5902         jmpTrueOrFalse(ifx, tlbl);
5903     } else {
5904       for(;(size--);offset++) {
5905         // normal case
5906         // result = left & right
5907         if(AOP_TYPE(right) == AOP_LIT){
5908           int t = (lit >> (offset*8)) & 0x0FFL;
5909           switch(t) { 
5910           case 0x00:
5911             pic16_emitcode("clrf","%s",
5912                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5913             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5914             break;
5915           case 0xff:
5916             pic16_emitcode("movf","%s,w",
5917                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5918             pic16_emitcode("movwf","%s",
5919                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5920             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5921             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5922             break;
5923           default:
5924             pic16_emitcode("movlw","0x%x",t);
5925             pic16_emitcode("andwf","%s,w",
5926                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5927             pic16_emitcode("movwf","%s",
5928                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5929               
5930             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5931             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5932             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5933           }
5934           continue;
5935         }
5936
5937         if (AOP_TYPE(left) == AOP_ACC) {
5938           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5939           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5940         } else {
5941           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5942           pic16_emitcode("andwf","%s,w",
5943                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5944           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5945           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5946         }
5947         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5948         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5949       }
5950     }
5951   }
5952
5953   release :
5954     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5955   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5956   pic16_freeAsmop(result,NULL,ic,TRUE);     
5957 }
5958
5959 /*-----------------------------------------------------------------*/
5960 /* genOr  - code for or                                            */
5961 /*-----------------------------------------------------------------*/
5962 static void genOr (iCode *ic, iCode *ifx)
5963 {
5964     operand *left, *right, *result;
5965     int size, offset=0;
5966     unsigned long lit = 0L;
5967
5968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5969
5970     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5971     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5972     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5973
5974     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5975
5976     /* if left is a literal & right is not then exchange them */
5977     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5978         AOP_NEEDSACC(left)) {
5979         operand *tmp = right ;
5980         right = left;
5981         left = tmp;
5982     }
5983
5984     /* if result = right then exchange them */
5985     if(pic16_sameRegs(AOP(result),AOP(right))){
5986         operand *tmp = right ;
5987         right = left;
5988         left = tmp;
5989     }
5990
5991     /* if right is bit then exchange them */
5992     if (AOP_TYPE(right) == AOP_CRY &&
5993         AOP_TYPE(left) != AOP_CRY){
5994         operand *tmp = right ;
5995         right = left;
5996         left = tmp;
5997     }
5998
5999     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6000
6001     if(AOP_TYPE(right) == AOP_LIT)
6002         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6003
6004     size = AOP_SIZE(result);
6005
6006     // if(bit | yy)
6007     // xx = bit | yy;
6008     if (AOP_TYPE(left) == AOP_CRY){
6009         if(AOP_TYPE(right) == AOP_LIT){
6010             // c = bit & literal;
6011             if(lit){
6012                 // lit != 0 => result = 1
6013                 if(AOP_TYPE(result) == AOP_CRY){
6014                   if(size)
6015                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6016                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6017                   //     AOP(result)->aopu.aop_dir,
6018                   //     AOP(result)->aopu.aop_dir);
6019                     else if(ifx)
6020                         continueIfTrue(ifx);
6021                     goto release;
6022                 }
6023             } else {
6024                 // lit == 0 => result = left
6025                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6026                     goto release;
6027                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6028             }
6029         } else {
6030             if (AOP_TYPE(right) == AOP_CRY){
6031               if(pic16_sameRegs(AOP(result),AOP(left))){
6032                 // c = bit | bit;
6033                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6034                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6035                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6036
6037                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6038                          AOP(result)->aopu.aop_dir,
6039                          AOP(result)->aopu.aop_dir);
6040                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6041                          AOP(right)->aopu.aop_dir,
6042                          AOP(right)->aopu.aop_dir);
6043                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6044                          AOP(result)->aopu.aop_dir,
6045                          AOP(result)->aopu.aop_dir);
6046               } else {
6047                 if( AOP_TYPE(result) == AOP_ACC) {
6048                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6049                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6050                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6051                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6052
6053                 } else {
6054
6055                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6056                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6057                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6058                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6059
6060                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6061                                  AOP(result)->aopu.aop_dir,
6062                                  AOP(result)->aopu.aop_dir);
6063                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6064                                  AOP(right)->aopu.aop_dir,
6065                                  AOP(right)->aopu.aop_dir);
6066                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6067                                  AOP(left)->aopu.aop_dir,
6068                                  AOP(left)->aopu.aop_dir);
6069                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6070                                  AOP(result)->aopu.aop_dir,
6071                                  AOP(result)->aopu.aop_dir);
6072                 }
6073               }
6074             } else {
6075                 // c = bit | val;
6076                 symbol *tlbl = newiTempLabel(NULL);
6077                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6078
6079
6080                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6081                 if( AOP_TYPE(right) == AOP_ACC) {
6082                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6083                   emitSKPNZ;
6084                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6085                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6086                 }
6087
6088
6089
6090                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6091                     pic16_emitcode(";XXX setb","c");
6092                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6093                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6094                 pic16_toBoolean(right);
6095                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6096                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6097                     jmpTrueOrFalse(ifx, tlbl);
6098                     goto release;
6099                 } else {
6100                     CLRC;
6101                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6102                 }
6103             }
6104         }
6105         // bit = c
6106         // val = c
6107         if(size)
6108             pic16_outBitC(result);
6109         // if(bit | ...)
6110         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6111             genIfxJump(ifx, "c");           
6112         goto release ;
6113     }
6114
6115     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6116     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6117     if((AOP_TYPE(right) == AOP_LIT) &&
6118        (AOP_TYPE(result) == AOP_CRY) &&
6119        (AOP_TYPE(left) != AOP_CRY)){
6120         if(lit){
6121           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6122             // result = 1
6123             if(size)
6124                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6125             else 
6126                 continueIfTrue(ifx);
6127             goto release;
6128         } else {
6129           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6130             // lit = 0, result = boolean(left)
6131             if(size)
6132                 pic16_emitcode(";XXX setb","c");
6133             pic16_toBoolean(right);
6134             if(size){
6135                 symbol *tlbl = newiTempLabel(NULL);
6136                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6137                 CLRC;
6138                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6139             } else {
6140                 genIfxJump (ifx,"a");
6141                 goto release;
6142             }
6143         }
6144         pic16_outBitC(result);
6145         goto release ;
6146     }
6147
6148     /* if left is same as result */
6149     if(pic16_sameRegs(AOP(result),AOP(left))){
6150       int know_W = -1;
6151       for(;size--; offset++,lit>>=8) {
6152         if(AOP_TYPE(right) == AOP_LIT){
6153           if((lit & 0xff) == 0)
6154             /*  or'ing with 0 has no effect */
6155             continue;
6156           else {
6157             int p = my_powof2(lit & 0xff);
6158             if(p>=0) {
6159               /* only one bit is set in the literal, so use a bsf instruction */
6160               pic16_emitpcode(POC_BSF,
6161                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6162             } else {
6163               if(know_W != (lit & 0xff))
6164                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6165               know_W = lit & 0xff;
6166               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6167             }
6168                     
6169           }
6170         } else {
6171           if (AOP_TYPE(left) == AOP_ACC) {
6172             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6173             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6174           } else {                  
6175             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6176             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6177
6178             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6179             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6180
6181           }
6182         }
6183       }
6184     } else {
6185         // left & result in different registers
6186         if(AOP_TYPE(result) == AOP_CRY){
6187             // result = bit
6188             // if(size), result in bit
6189             // if(!size && ifx), conditional oper: if(left | right)
6190             symbol *tlbl = newiTempLabel(NULL);
6191             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6192             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6193
6194
6195             if(size)
6196                 pic16_emitcode(";XXX setb","c");
6197             while(sizer--){
6198                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6199                 pic16_emitcode(";XXX orl","a,%s",
6200                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6201                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6202                 offset++;
6203             }
6204             if(size){
6205                 CLRC;
6206                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6207                 pic16_outBitC(result);
6208             } else if(ifx)
6209                 jmpTrueOrFalse(ifx, tlbl);
6210         } else for(;(size--);offset++){
6211           // normal case
6212           // result = left & right
6213           if(AOP_TYPE(right) == AOP_LIT){
6214             int t = (lit >> (offset*8)) & 0x0FFL;
6215             switch(t) { 
6216             case 0x00:
6217               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6218               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6219
6220               pic16_emitcode("movf","%s,w",
6221                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6222               pic16_emitcode("movwf","%s",
6223                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6224               break;
6225             default:
6226               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6227               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6228               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6229
6230               pic16_emitcode("movlw","0x%x",t);
6231               pic16_emitcode("iorwf","%s,w",
6232                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6233               pic16_emitcode("movwf","%s",
6234                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6235               
6236             }
6237             continue;
6238           }
6239
6240           // faster than result <- left, anl result,right
6241           // and better if result is SFR
6242           if (AOP_TYPE(left) == AOP_ACC) {
6243             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6244             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6245           } else {
6246             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6247             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6248
6249             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6250             pic16_emitcode("iorwf","%s,w",
6251                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6252           }
6253           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6254           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6255         }
6256     }
6257
6258 release :
6259     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6261     pic16_freeAsmop(result,NULL,ic,TRUE);     
6262 }
6263
6264 /*-----------------------------------------------------------------*/
6265 /* genXor - code for xclusive or                                   */
6266 /*-----------------------------------------------------------------*/
6267 static void genXor (iCode *ic, iCode *ifx)
6268 {
6269   operand *left, *right, *result;
6270   int size, offset=0;
6271   unsigned long lit = 0L;
6272
6273   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6274
6275   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6276   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6277   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6278
6279   /* if left is a literal & right is not ||
6280      if left needs acc & right does not */
6281   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6282       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6283     operand *tmp = right ;
6284     right = left;
6285     left = tmp;
6286   }
6287
6288   /* if result = right then exchange them */
6289   if(pic16_sameRegs(AOP(result),AOP(right))){
6290     operand *tmp = right ;
6291     right = left;
6292     left = tmp;
6293   }
6294
6295   /* if right is bit then exchange them */
6296   if (AOP_TYPE(right) == AOP_CRY &&
6297       AOP_TYPE(left) != AOP_CRY){
6298     operand *tmp = right ;
6299     right = left;
6300     left = tmp;
6301   }
6302   if(AOP_TYPE(right) == AOP_LIT)
6303     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6304
6305   size = AOP_SIZE(result);
6306
6307   // if(bit ^ yy)
6308   // xx = bit ^ yy;
6309   if (AOP_TYPE(left) == AOP_CRY){
6310     if(AOP_TYPE(right) == AOP_LIT){
6311       // c = bit & literal;
6312       if(lit>>1){
6313         // lit>>1  != 0 => result = 1
6314         if(AOP_TYPE(result) == AOP_CRY){
6315           if(size)
6316             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6317             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6318           else if(ifx)
6319             continueIfTrue(ifx);
6320           goto release;
6321         }
6322         pic16_emitcode("setb","c");
6323       } else{
6324         // lit == (0 or 1)
6325         if(lit == 0){
6326           // lit == 0, result = left
6327           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6328             goto release;
6329           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6330         } else{
6331           // lit == 1, result = not(left)
6332           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6333             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6334             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6335             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6336             goto release;
6337           } else {
6338             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6339             pic16_emitcode("cpl","c");
6340           }
6341         }
6342       }
6343
6344     } else {
6345       // right != literal
6346       symbol *tlbl = newiTempLabel(NULL);
6347       if (AOP_TYPE(right) == AOP_CRY){
6348         // c = bit ^ bit;
6349         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6350       }
6351       else{
6352         int sizer = AOP_SIZE(right);
6353         // c = bit ^ val
6354         // if val>>1 != 0, result = 1
6355         pic16_emitcode("setb","c");
6356         while(sizer){
6357           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6358           if(sizer == 1)
6359             // test the msb of the lsb
6360             pic16_emitcode("anl","a,#0xfe");
6361           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6362           sizer--;
6363         }
6364         // val = (0,1)
6365         pic16_emitcode("rrc","a");
6366       }
6367       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6368       pic16_emitcode("cpl","c");
6369       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6370     }
6371     // bit = c
6372     // val = c
6373     if(size)
6374       pic16_outBitC(result);
6375     // if(bit | ...)
6376     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6377       genIfxJump(ifx, "c");           
6378     goto release ;
6379   }
6380
6381   if(pic16_sameRegs(AOP(result),AOP(left))){
6382     /* if left is same as result */
6383     for(;size--; offset++) {
6384       if(AOP_TYPE(right) == AOP_LIT){
6385         int t  = (lit >> (offset*8)) & 0x0FFL;
6386         if(t == 0x00L)
6387           continue;
6388         else
6389           if (IS_AOP_PREG(left)) {
6390             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6391             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6392             pic16_aopPut(AOP(result),"a",offset);
6393           } else {
6394             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6395             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6396             pic16_emitcode("xrl","%s,%s",
6397                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6398                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6399           }
6400       } else {
6401         if (AOP_TYPE(left) == AOP_ACC)
6402           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6403         else {
6404           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6405           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6406 /*
6407           if (IS_AOP_PREG(left)) {
6408             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6409             pic16_aopPut(AOP(result),"a",offset);
6410           } else
6411             pic16_emitcode("xrl","%s,a",
6412                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6413 */
6414         }
6415       }
6416     }
6417   } else {
6418     // left & result in different registers
6419     if(AOP_TYPE(result) == AOP_CRY){
6420       // result = bit
6421       // if(size), result in bit
6422       // if(!size && ifx), conditional oper: if(left ^ right)
6423       symbol *tlbl = newiTempLabel(NULL);
6424       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6425       if(size)
6426         pic16_emitcode("setb","c");
6427       while(sizer--){
6428         if((AOP_TYPE(right) == AOP_LIT) &&
6429            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6430           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6431         } else {
6432           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6433           pic16_emitcode("xrl","a,%s",
6434                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6435         }
6436         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6437         offset++;
6438       }
6439       if(size){
6440         CLRC;
6441         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6442         pic16_outBitC(result);
6443       } else if(ifx)
6444         jmpTrueOrFalse(ifx, tlbl);
6445     } else for(;(size--);offset++){
6446       // normal case
6447       // result = left & right
6448       if(AOP_TYPE(right) == AOP_LIT){
6449         int t = (lit >> (offset*8)) & 0x0FFL;
6450         switch(t) { 
6451         case 0x00:
6452           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6454           pic16_emitcode("movf","%s,w",
6455                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6456           pic16_emitcode("movwf","%s",
6457                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6458           break;
6459         case 0xff:
6460           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6461           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6462           pic16_emitcode("comf","%s,w",
6463                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6464           pic16_emitcode("movwf","%s",
6465                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6466           break;
6467         default:
6468           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6469           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6470           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6471           pic16_emitcode("movlw","0x%x",t);
6472           pic16_emitcode("xorwf","%s,w",
6473                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6474           pic16_emitcode("movwf","%s",
6475                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6476
6477         }
6478         continue;
6479       }
6480
6481       // faster than result <- left, anl result,right
6482       // and better if result is SFR
6483       if (AOP_TYPE(left) == AOP_ACC) {
6484         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6485         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6486       } else {
6487         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6488         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6489         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6490         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6491       }
6492       if ( AOP_TYPE(result) != AOP_ACC){
6493         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6494         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6495       }
6496     }
6497   }
6498
6499   release :
6500     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6501   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6502   pic16_freeAsmop(result,NULL,ic,TRUE);     
6503 }
6504
6505 /*-----------------------------------------------------------------*/
6506 /* genInline - write the inline code out                           */
6507 /*-----------------------------------------------------------------*/
6508 static void genInline (iCode *ic)
6509 {
6510   char *buffer, *bp, *bp1;
6511     
6512         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6513
6514         _G.inLine += (!options.asmpeep);
6515
6516         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6517         strcpy(buffer,IC_INLINE(ic));
6518
6519 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6520
6521         /* emit each line as a code */
6522         while (*bp) {
6523                 if (*bp == '\n') {
6524                         *bp++ = '\0';
6525
6526                         if(*bp1)
6527 #if 0
6528                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6529 #else
6530                                 pic16_addpCode2pBlock(pb, pic16_AssembleLine(bp1, 1));
6531 #endif
6532                         bp1 = bp;
6533                 } else {
6534                         if (*bp == ':') {
6535                                 bp++;
6536                                 *bp = '\0';
6537                                 bp++;
6538                                 pic16_emitcode(bp1,"");
6539                                 bp1 = bp;
6540                         } else
6541                                 bp++;
6542                 }
6543         }
6544
6545         if ((bp1 != bp) && *bp1)
6546 #if 0
6547                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6548 #else
6549                 pic16_addpCode2pBlock(pb, pic16_AssembleLine(bp1, 1));
6550 #endif
6551
6552
6553     Safe_free(buffer);
6554
6555     _G.inLine -= (!options.asmpeep);
6556 }
6557
6558 /*-----------------------------------------------------------------*/
6559 /* genRRC - rotate right with carry                                */
6560 /*-----------------------------------------------------------------*/
6561 static void genRRC (iCode *ic)
6562 {
6563   operand *left , *result ;
6564   int size, offset = 0, same;
6565
6566   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6567
6568   /* rotate right with carry */
6569   left = IC_LEFT(ic);
6570   result=IC_RESULT(ic);
6571   pic16_aopOp (left,ic,FALSE);
6572   pic16_aopOp (result,ic,FALSE);
6573
6574   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6575
6576   same = pic16_sameRegs(AOP(result),AOP(left));
6577
6578   size = AOP_SIZE(result);    
6579
6580   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6581
6582   /* get the lsb and put it into the carry */
6583   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6584
6585   offset = 0 ;
6586
6587   while(size--) {
6588
6589     if(same) {
6590       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6591     } else {
6592       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6593       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6594     }
6595
6596     offset++;
6597   }
6598
6599   pic16_freeAsmop(left,NULL,ic,TRUE);
6600   pic16_freeAsmop(result,NULL,ic,TRUE);
6601 }
6602
6603 /*-----------------------------------------------------------------*/
6604 /* genRLC - generate code for rotate left with carry               */
6605 /*-----------------------------------------------------------------*/
6606 static void genRLC (iCode *ic)
6607 {    
6608   operand *left , *result ;
6609   int size, offset = 0;
6610   int same;
6611
6612   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6613   /* rotate right with carry */
6614   left = IC_LEFT(ic);
6615   result=IC_RESULT(ic);
6616   pic16_aopOp (left,ic,FALSE);
6617   pic16_aopOp (result,ic,FALSE);
6618
6619   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6620
6621   same = pic16_sameRegs(AOP(result),AOP(left));
6622
6623   /* move it to the result */
6624   size = AOP_SIZE(result);    
6625
6626   /* get the msb and put it into the carry */
6627   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6628
6629   offset = 0 ;
6630
6631   while(size--) {
6632
6633     if(same) {
6634       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6635     } else {
6636       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6637       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6638     }
6639
6640     offset++;
6641   }
6642
6643
6644   pic16_freeAsmop(left,NULL,ic,TRUE);
6645   pic16_freeAsmop(result,NULL,ic,TRUE);
6646 }
6647
6648
6649 /* gpasm can get the highest order bit with HIGH/UPPER
6650  * so the following probably is not needed -- VR */
6651  
6652 /*-----------------------------------------------------------------*/
6653 /* genGetHbit - generates code get highest order bit               */
6654 /*-----------------------------------------------------------------*/
6655 static void genGetHbit (iCode *ic)
6656 {
6657     operand *left, *result;
6658     left = IC_LEFT(ic);
6659     result=IC_RESULT(ic);
6660     pic16_aopOp (left,ic,FALSE);
6661     pic16_aopOp (result,ic,FALSE);
6662
6663     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6664     /* get the highest order byte into a */
6665     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6666     if(AOP_TYPE(result) == AOP_CRY){
6667         pic16_emitcode("rlc","a");
6668         pic16_outBitC(result);
6669     }
6670     else{
6671         pic16_emitcode("rl","a");
6672         pic16_emitcode("anl","a,#0x01");
6673         pic16_outAcc(result);
6674     }
6675
6676
6677     pic16_freeAsmop(left,NULL,ic,TRUE);
6678     pic16_freeAsmop(result,NULL,ic,TRUE);
6679 }
6680
6681 #if 0
6682 /*-----------------------------------------------------------------*/
6683 /* AccRol - rotate left accumulator by known count                 */
6684 /*-----------------------------------------------------------------*/
6685 static void AccRol (int shCount)
6686 {
6687     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6688     shCount &= 0x0007;              // shCount : 0..7
6689     switch(shCount){
6690         case 0 :
6691             break;
6692         case 1 :
6693             pic16_emitcode("rl","a");
6694             break;
6695         case 2 :
6696             pic16_emitcode("rl","a");
6697             pic16_emitcode("rl","a");
6698             break;
6699         case 3 :
6700             pic16_emitcode("swap","a");
6701             pic16_emitcode("rr","a");
6702             break;
6703         case 4 :
6704             pic16_emitcode("swap","a");
6705             break;
6706         case 5 :
6707             pic16_emitcode("swap","a");
6708             pic16_emitcode("rl","a");
6709             break;
6710         case 6 :
6711             pic16_emitcode("rr","a");
6712             pic16_emitcode("rr","a");
6713             break;
6714         case 7 :
6715             pic16_emitcode("rr","a");
6716             break;
6717     }
6718 }
6719 #endif
6720
6721 /*-----------------------------------------------------------------*/
6722 /* AccLsh - left shift accumulator by known count                  */
6723 /*-----------------------------------------------------------------*/
6724 static void AccLsh (int shCount)
6725 {
6726         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6727         switch(shCount){
6728                 case 0 :
6729                         return;
6730                         break;
6731                 case 1 :
6732                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6733                         break;
6734                 case 2 :
6735                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6736                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6737                         break;
6738                 case 3 :
6739                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6740                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6741                         break;
6742                 case 4 :
6743                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6744                         break;
6745                 case 5 :
6746                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6747                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6748                         break;
6749                 case 6 :
6750                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6751                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6752                         break;
6753                 case 7 :
6754                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6755                         break;
6756         }
6757
6758         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* AccRsh - right shift accumulator by known count                 */
6763 /*-----------------------------------------------------------------*/
6764 static void AccRsh (int shCount, int andmask)
6765 {
6766         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6767         switch(shCount){
6768                 case 0 :
6769                         return; break;
6770                 case 1 :
6771                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6772 //                      andmask = 0;    /* no need */
6773                         break;
6774                 case 2 :
6775                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6776                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6777 //                      andmask = 0;    /* no need */
6778                         break;
6779                 case 3 :
6780                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6781                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6782                         break;
6783                 case 4 :
6784                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6785                         break;
6786                 case 5 :
6787                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6788                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6789                         break;
6790                 case 6 :
6791                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6792                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6793                         break;
6794                 case 7 :
6795                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6796                         break;
6797         }
6798         
6799         if(andmask)
6800                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6801         else
6802                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6803 }
6804
6805 #if 0
6806 /*-----------------------------------------------------------------*/
6807 /* AccSRsh - signed right shift accumulator by known count                 */
6808 /*-----------------------------------------------------------------*/
6809 static void AccSRsh (int shCount)
6810 {
6811     symbol *tlbl ;
6812     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6813     if(shCount != 0){
6814         if(shCount == 1){
6815             pic16_emitcode("mov","c,acc.7");
6816             pic16_emitcode("rrc","a");
6817         } else if(shCount == 2){
6818             pic16_emitcode("mov","c,acc.7");
6819             pic16_emitcode("rrc","a");
6820             pic16_emitcode("mov","c,acc.7");
6821             pic16_emitcode("rrc","a");
6822         } else {
6823             tlbl = newiTempLabel(NULL);
6824             /* rotate right accumulator */
6825             AccRol(8 - shCount);
6826             /* and kill the higher order bits */
6827             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6828             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6829             pic16_emitcode("orl","a,#0x%02x",
6830                      (unsigned char)~SRMask[shCount]);
6831             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6832         }
6833     }
6834 }
6835 #endif
6836 /*-----------------------------------------------------------------*/
6837 /* shiftR1Left2Result - shift right one byte from left to result   */
6838 /*-----------------------------------------------------------------*/
6839 static void shiftR1Left2ResultSigned (operand *left, int offl,
6840                                 operand *result, int offr,
6841                                 int shCount)
6842 {
6843   int same;
6844
6845   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6846
6847   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6848
6849   switch(shCount) {
6850   case 1:
6851     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6852     if(same) 
6853       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6854     else {
6855       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6857     }
6858
6859     break;
6860   case 2:
6861
6862     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6863     if(same) 
6864       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6865     else {
6866       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6867       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6868     }
6869     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6870     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6871
6872     break;
6873
6874   case 3:
6875     if(same)
6876       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6877     else {
6878       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6879       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6880     }
6881
6882     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6883     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6884     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6885
6886     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6887     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6888
6889     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6890     break;
6891
6892   case 4:
6893     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6894     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6895     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6896     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6897     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6898     break;
6899   case 5:
6900     if(same) {
6901       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6902     } else {
6903       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6904       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6905     }
6906     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6907     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6908     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6909     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6910     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6911     break;
6912
6913   case 6:
6914     if(same) {
6915       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6916       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6917       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6918       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6919       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6920       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6921     } else {
6922       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6923       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6924       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6925       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6926       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6927     }
6928     break;
6929
6930   case 7:
6931     if(same) {
6932       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6933       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6934       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6935       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6936     } else {
6937       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6938       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6939       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6940     }
6941
6942   default:
6943     break;
6944   }
6945 }
6946
6947 /*-----------------------------------------------------------------*/
6948 /* shiftR1Left2Result - shift right one byte from left to result   */
6949 /*-----------------------------------------------------------------*/
6950 static void shiftR1Left2Result (operand *left, int offl,
6951                                 operand *result, int offr,
6952                                 int shCount, int sign)
6953 {
6954   int same;
6955
6956   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6957
6958   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6959
6960   /* Copy the msb into the carry if signed. */
6961   if(sign) {
6962     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6963     return;
6964   }
6965
6966
6967
6968   switch(shCount) {
6969   case 1:
6970     emitCLRC;
6971     if(same) 
6972       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6973     else {
6974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6975       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6976     }
6977     break;
6978   case 2:
6979     emitCLRC;
6980     if(same) {
6981       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6982     } else {
6983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6984       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6985     }
6986     emitCLRC;
6987     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6988
6989     break;
6990   case 3:
6991     if(same)
6992       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6993     else {
6994       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6995       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6996     }
6997
6998     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6999     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7000     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7001     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7002     break;
7003       
7004   case 4:
7005     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7006     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7007     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7008     break;
7009
7010   case 5:
7011     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7012     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7013     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7014     emitCLRC;
7015     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7016
7017     break;
7018   case 6:
7019
7020     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7021     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7022     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7023     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7024     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7025     break;
7026
7027   case 7:
7028
7029     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7030     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7031     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7032
7033     break;
7034
7035   default:
7036     break;
7037   }
7038 }
7039
7040 /*-----------------------------------------------------------------*/
7041 /* shiftL1Left2Result - shift left one byte from left to result    */
7042 /*-----------------------------------------------------------------*/
7043 static void shiftL1Left2Result (operand *left, int offl,
7044                                 operand *result, int offr, int shCount)
7045 {
7046   int same;
7047
7048   //    char *l;
7049   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7050
7051   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7052   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7053     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7054     //    MOVA(l);
7055     /* shift left accumulator */
7056     //AccLsh(shCount); // don't comment out just yet...
7057   //    pic16_aopPut(AOP(result),"a",offr);
7058
7059   switch(shCount) {
7060   case 1:
7061     /* Shift left 1 bit position */
7062     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7063     if(same) {
7064       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7065     } else {
7066       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7067       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7068     }
7069     break;
7070   case 2:
7071     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7072     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7073     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7074     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7075     break;
7076   case 3:
7077     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7078     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7079     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7080     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7081     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7082     break;
7083   case 4:
7084     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7085     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7086     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7087     break;
7088   case 5:
7089     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7090     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7091     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7092     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7093     break;
7094   case 6:
7095     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7096     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7097     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7098     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7099     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7100     break;
7101   case 7:
7102     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7103     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7104     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7105     break;
7106
7107   default:
7108     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7109   }
7110
7111 }
7112
7113 /*-----------------------------------------------------------------*/
7114 /* movLeft2Result - move byte from left to result                  */
7115 /*-----------------------------------------------------------------*/
7116 static void movLeft2Result (operand *left, int offl,
7117                             operand *result, int offr)
7118 {
7119   char *l;
7120   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7121   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7122     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7123
7124     if (*l == '@' && (IS_AOP_PREG(result))) {
7125       pic16_emitcode("mov","a,%s",l);
7126       pic16_aopPut(AOP(result),"a",offr);
7127     } else {
7128       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7129       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7130     }
7131   }
7132 }
7133
7134 /*-----------------------------------------------------------------*/
7135 /* shiftL2Left2Result - shift left two bytes from left to result   */
7136 /*-----------------------------------------------------------------*/
7137 static void shiftL2Left2Result (operand *left, int offl,
7138                                 operand *result, int offr, int shCount)
7139 {
7140   int same = pic16_sameRegs(AOP(result), AOP(left));
7141   int i;
7142
7143   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7144
7145   if (same && (offl != offr)) { // shift bytes
7146     if (offr > offl) {
7147        for(i=1;i>-1;i--) {
7148          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7149          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7150        }
7151     } else { // just treat as different later on
7152                 same = 0;
7153     }
7154   }
7155
7156   if(same) {
7157     switch(shCount) {
7158     case 0:
7159       break;
7160     case 1:
7161     case 2:
7162     case 3:
7163
7164       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7165       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7166       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7167
7168       while(--shCount) {
7169                 emitCLRC;
7170                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7171                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7172       }
7173
7174       break;
7175     case 4:
7176     case 5:
7177       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7178       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7179       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7180       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7181       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7182       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7183       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7184       if(shCount >=5) {
7185                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7186                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7187       }
7188       break;
7189     case 6:
7190       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7191       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7192       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7193       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7194       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7195       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7196       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7197       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7198       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7199       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7200       break;
7201     case 7:
7202       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7203       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7204       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7205       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7206       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7207     }
7208
7209   } else {
7210     switch(shCount) {
7211     case 0:
7212       break;
7213     case 1:
7214     case 2:
7215     case 3:
7216       /* note, use a mov/add for the shift since the mov has a
7217          chance of getting optimized out */
7218       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7219       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7220       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7221       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7222       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7223
7224       while(--shCount) {
7225                 emitCLRC;
7226                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7227                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7228       }
7229       break;
7230
7231     case 4:
7232     case 5:
7233       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7234       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7235       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7236       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7237       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7238       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7239       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7240       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7241
7242
7243       if(shCount == 5) {
7244                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7245                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7246       }
7247       break;
7248     case 6:
7249       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7250       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7251       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7252       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7253
7254       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7255       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7256       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7257       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7258       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7259       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7260       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7261       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7262       break;
7263     case 7:
7264       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7265       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7266       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7267       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7268       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7269     }
7270   }
7271
7272 }
7273 /*-----------------------------------------------------------------*/
7274 /* shiftR2Left2Result - shift right two bytes from left to result  */
7275 /*-----------------------------------------------------------------*/
7276 static void shiftR2Left2Result (operand *left, int offl,
7277                                 operand *result, int offr,
7278                                 int shCount, int sign)
7279 {
7280   int same = pic16_sameRegs(AOP(result), AOP(left));
7281   int i;
7282   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7283
7284   if (same && (offl != offr)) { // shift right bytes
7285     if (offr < offl) {
7286        for(i=0;i<2;i++) {
7287          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7288          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7289        }
7290     } else { // just treat as different later on
7291                 same = 0;
7292     }
7293   }
7294
7295   switch(shCount) {
7296   case 0:
7297     break;
7298   case 1:
7299   case 2:
7300   case 3:
7301     if(sign)
7302       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7303     else
7304       emitCLRC;
7305
7306     if(same) {
7307       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7308       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7309     } else {
7310       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7311       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7312       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7313       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7314     }
7315
7316     while(--shCount) {
7317       if(sign)
7318                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7319       else
7320                 emitCLRC;
7321       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7322       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7323     }
7324     break;
7325   case 4:
7326   case 5:
7327     if(same) {
7328
7329       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7330       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7331       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7332
7333       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7334       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7335       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7336       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7337     } else {
7338       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7339       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7340       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7341
7342       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7343       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7344       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7345       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7346       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7347     }
7348
7349     if(shCount >=5) {
7350       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7351       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7352     }
7353
7354     if(sign) {
7355       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7356       pic16_emitpcode(POC_BTFSC, 
7357                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7358       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7359     }
7360
7361     break;
7362
7363   case 6:
7364     if(same) {
7365
7366       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7367       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7368
7369       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7370       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7371       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7372       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7373       if(sign) {
7374         pic16_emitpcode(POC_BTFSC, 
7375                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7376         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7377       }
7378       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7379       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7380       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7381       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7382     } else {
7383       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7384       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7385       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7386       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7387       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7388       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7389       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7390       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7391       if(sign) {
7392         pic16_emitpcode(POC_BTFSC, 
7393                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7394         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7395       }
7396       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7397       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7398
7399         
7400     }
7401
7402     break;
7403   case 7:
7404     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7405     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7406     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7407     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7408     if(sign) {
7409       emitSKPNC;
7410       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7411     } else 
7412       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7413   }
7414 }
7415
7416
7417 /*-----------------------------------------------------------------*/
7418 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7419 /*-----------------------------------------------------------------*/
7420 static void shiftLLeftOrResult (operand *left, int offl,
7421                                 operand *result, int offr, int shCount)
7422 {
7423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7424
7425     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7426     /* shift left accumulator */
7427     AccLsh(shCount);
7428     /* or with result */
7429     /* back to result */
7430     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7431 }
7432
7433 /*-----------------------------------------------------------------*/
7434 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7435 /*-----------------------------------------------------------------*/
7436 static void shiftRLeftOrResult (operand *left, int offl,
7437                                 operand *result, int offr, int shCount)
7438 {
7439     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7440     
7441     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7442     /* shift right accumulator */
7443     AccRsh(shCount, 1);
7444     /* or with result */
7445     /* back to result */
7446     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7447 }
7448
7449 /*-----------------------------------------------------------------*/
7450 /* genlshOne - left shift a one byte quantity by known count       */
7451 /*-----------------------------------------------------------------*/
7452 static void genlshOne (operand *result, operand *left, int shCount)
7453 {       
7454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7456 }
7457
7458 /*-----------------------------------------------------------------*/
7459 /* genlshTwo - left shift two bytes by known amount != 0           */
7460 /*-----------------------------------------------------------------*/
7461 static void genlshTwo (operand *result,operand *left, int shCount)
7462 {
7463     int size;
7464     
7465     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7466     size = pic16_getDataSize(result);
7467
7468     /* if shCount >= 8 */
7469     if (shCount >= 8) {
7470         shCount -= 8 ;
7471
7472         if (size > 1){
7473             if (shCount)
7474                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7475             else 
7476                 movLeft2Result(left, LSB, result, MSB16);
7477         }
7478         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7479     }
7480
7481     /*  1 <= shCount <= 7 */
7482     else {  
7483         if(size == 1)
7484             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7485         else 
7486             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7487     }
7488 }
7489
7490 /*-----------------------------------------------------------------*/
7491 /* shiftLLong - shift left one long from left to result            */
7492 /* offr = LSB or MSB16                                             */
7493 /*-----------------------------------------------------------------*/
7494 static void shiftLLong (operand *left, operand *result, int offr )
7495 {
7496     int size = AOP_SIZE(result);
7497     int same = pic16_sameRegs(AOP(left),AOP(result));
7498         int i;
7499
7500     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7501
7502         if (same && (offr == MSB16)) { //shift one byte
7503                 for(i=size-1;i>=MSB16;i--) {
7504                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7505                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7506                 }
7507         } else {
7508                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7509         }
7510         
7511     if (size >= LSB+offr ){
7512                 if (same) {
7513                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7514                 } else {
7515                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7516                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7517                 }
7518          }
7519
7520     if(size >= MSB16+offr){
7521                 if (same) {
7522                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7523                 } else {
7524                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7525                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7526                 }
7527     }
7528
7529     if(size >= MSB24+offr){
7530                 if (same) {
7531                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7532                 } else {
7533                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7534                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7535                 }
7536     }
7537
7538     if(size > MSB32+offr){
7539                 if (same) {
7540                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7541                 } else {
7542                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7543                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7544                 }
7545     }
7546     if(offr != LSB)
7547                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7548
7549 }
7550
7551 /*-----------------------------------------------------------------*/
7552 /* genlshFour - shift four byte by a known amount != 0             */
7553 /*-----------------------------------------------------------------*/
7554 static void genlshFour (operand *result, operand *left, int shCount)
7555 {
7556     int size;
7557
7558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7559     size = AOP_SIZE(result);
7560
7561     /* if shifting more that 3 bytes */
7562     if (shCount >= 24 ) {
7563         shCount -= 24;
7564         if (shCount)
7565             /* lowest order of left goes to the highest
7566             order of the destination */
7567             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7568         else
7569             movLeft2Result(left, LSB, result, MSB32);
7570
7571                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7572                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7573                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7574
7575         return;
7576     }
7577
7578     /* more than two bytes */
7579     else if ( shCount >= 16 ) {
7580         /* lower order two bytes goes to higher order two bytes */
7581         shCount -= 16;
7582         /* if some more remaining */
7583         if (shCount)
7584             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7585         else {
7586             movLeft2Result(left, MSB16, result, MSB32);
7587             movLeft2Result(left, LSB, result, MSB24);
7588         }
7589                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7590                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7591         return;
7592     }    
7593
7594     /* if more than 1 byte */
7595     else if ( shCount >= 8 ) {
7596         /* lower order three bytes goes to higher order  three bytes */
7597         shCount -= 8;
7598         if(size == 2){
7599             if(shCount)
7600                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7601             else
7602                 movLeft2Result(left, LSB, result, MSB16);
7603         }
7604         else{   /* size = 4 */
7605             if(shCount == 0){
7606                 movLeft2Result(left, MSB24, result, MSB32);
7607                 movLeft2Result(left, MSB16, result, MSB24);
7608                 movLeft2Result(left, LSB, result, MSB16);
7609                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7610             }
7611             else if(shCount == 1)
7612                 shiftLLong(left, result, MSB16);
7613             else{
7614                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7615                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7616                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7617                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7618             }
7619         }
7620     }
7621
7622     /* 1 <= shCount <= 7 */
7623     else if(shCount <= 3)
7624     { 
7625         shiftLLong(left, result, LSB);
7626         while(--shCount >= 1)
7627             shiftLLong(result, result, LSB);
7628     }
7629     /* 3 <= shCount <= 7, optimize */
7630     else{
7631         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7632         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7633         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7634     }
7635 }
7636
7637 /*-----------------------------------------------------------------*/
7638 /* genLeftShiftLiteral - left shifting by known count              */
7639 /*-----------------------------------------------------------------*/
7640 static void genLeftShiftLiteral (operand *left,
7641                                  operand *right,
7642                                  operand *result,
7643                                  iCode *ic)
7644 {    
7645     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7646     int size;
7647
7648     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7649     pic16_freeAsmop(right,NULL,ic,TRUE);
7650
7651     pic16_aopOp(left,ic,FALSE);
7652     pic16_aopOp(result,ic,FALSE);
7653
7654     size = getSize(operandType(result));
7655
7656 #if VIEW_SIZE
7657     pic16_emitcode("; shift left ","result %d, left %d",size,
7658              AOP_SIZE(left));
7659 #endif
7660
7661     /* I suppose that the left size >= result size */
7662     if(shCount == 0){
7663         while(size--){
7664             movLeft2Result(left, size, result, size);
7665         }
7666     }
7667
7668     else if(shCount >= (size * 8))
7669         while(size--)
7670             pic16_aopPut(AOP(result),zero,size);
7671     else{
7672         switch (size) {
7673             case 1:
7674                 genlshOne (result,left,shCount);
7675                 break;
7676
7677             case 2:
7678             case 3:
7679                 genlshTwo (result,left,shCount);
7680                 break;
7681
7682             case 4:
7683                 genlshFour (result,left,shCount);
7684                 break;
7685         }
7686     }
7687     pic16_freeAsmop(left,NULL,ic,TRUE);
7688     pic16_freeAsmop(result,NULL,ic,TRUE);
7689 }
7690
7691 /*-----------------------------------------------------------------*
7692  * genMultiAsm - repeat assembly instruction for size of register.
7693  * if endian == 1, then the high byte (i.e base address + size of 
7694  * register) is used first else the low byte is used first;
7695  *-----------------------------------------------------------------*/
7696 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7697 {
7698
7699   int offset = 0;
7700
7701   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7702
7703   if(!reg)
7704     return;
7705
7706   if(!endian) {
7707     endian = 1;
7708   } else {
7709     endian = -1;
7710     offset = size-1;
7711   }
7712
7713   while(size--) {
7714     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7715     offset += endian;
7716   }
7717
7718 }
7719 /*-----------------------------------------------------------------*/
7720 /* genLeftShift - generates code for left shifting                 */
7721 /*-----------------------------------------------------------------*/
7722 static void genLeftShift (iCode *ic)
7723 {
7724   operand *left,*right, *result;
7725   int size, offset;
7726   char *l;
7727   symbol *tlbl , *tlbl1;
7728   pCodeOp *pctemp;
7729
7730   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7731
7732   right = IC_RIGHT(ic);
7733   left  = IC_LEFT(ic);
7734   result = IC_RESULT(ic);
7735
7736   pic16_aopOp(right,ic,FALSE);
7737
7738   /* if the shift count is known then do it 
7739      as efficiently as possible */
7740   if (AOP_TYPE(right) == AOP_LIT) {
7741     genLeftShiftLiteral (left,right,result,ic);
7742     return ;
7743   }
7744
7745   /* shift count is unknown then we have to form 
7746      a loop get the loop count in B : Note: we take
7747      only the lower order byte since shifting
7748      more that 32 bits make no sense anyway, ( the
7749      largest size of an object can be only 32 bits ) */  
7750
7751     
7752   pic16_aopOp(left,ic,FALSE);
7753   pic16_aopOp(result,ic,FALSE);
7754
7755   /* now move the left to the result if they are not the
7756      same */
7757   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7758       AOP_SIZE(result) > 1) {
7759
7760     size = AOP_SIZE(result);
7761     offset=0;
7762     while (size--) {
7763       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7764       if (*l == '@' && (IS_AOP_PREG(result))) {
7765
7766         pic16_emitcode("mov","a,%s",l);
7767         pic16_aopPut(AOP(result),"a",offset);
7768       } else {
7769         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7770         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7771         //pic16_aopPut(AOP(result),l,offset);
7772       }
7773       offset++;
7774     }
7775   }
7776
7777   size = AOP_SIZE(result);
7778
7779   /* if it is only one byte then */
7780   if (size == 1) {
7781     if(optimized_for_speed) {
7782       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7783       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7784       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7785       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7786       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7787       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7788       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7789       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7790       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7791       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7792       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7793       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7794     } else {
7795
7796       tlbl = newiTempLabel(NULL);
7797       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7798                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7799                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7800       }
7801
7802       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7803       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7804       pic16_emitpLabel(tlbl->key);
7805       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7806       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7807       emitSKPC;
7808       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7809     }
7810     goto release ;
7811   }
7812     
7813   if (pic16_sameRegs(AOP(left),AOP(result))) {
7814
7815     tlbl = newiTempLabel(NULL);
7816     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7817     genMultiAsm(POC_RRCF, result, size,1);
7818     pic16_emitpLabel(tlbl->key);
7819     genMultiAsm(POC_RLCF, result, size,0);
7820     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7821     emitSKPC;
7822     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7823     goto release;
7824   }
7825
7826   //tlbl = newiTempLabel(NULL);
7827   //offset = 0 ;   
7828   //tlbl1 = newiTempLabel(NULL);
7829
7830   //reAdjustPreg(AOP(result));    
7831     
7832   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7833   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7834   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7835   //MOVA(l);
7836   //pic16_emitcode("add","a,acc");         
7837   //pic16_aopPut(AOP(result),"a",offset++);
7838   //while (--size) {
7839   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7840   //  MOVA(l);
7841   //  pic16_emitcode("rlc","a");         
7842   //  pic16_aopPut(AOP(result),"a",offset++);
7843   //}
7844   //reAdjustPreg(AOP(result));
7845
7846   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7847   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7848
7849
7850   tlbl = newiTempLabel(NULL);
7851   tlbl1= newiTempLabel(NULL);
7852
7853   size = AOP_SIZE(result);
7854   offset = 1;
7855
7856   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7857
7858   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7859
7860   /* offset should be 0, 1 or 3 */
7861   
7862   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
7863   emitSKPNZ;
7864   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7865
7866   pic16_emitpcode(POC_MOVWF, pctemp);
7867
7868
7869   pic16_emitpLabel(tlbl->key);
7870
7871   emitCLRC;
7872   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7873   while(--size)
7874     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7875
7876   pic16_emitpcode(POC_DECFSZ,  pctemp);
7877   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7878   pic16_emitpLabel(tlbl1->key);
7879
7880   pic16_popReleaseTempReg(pctemp);
7881
7882
7883  release:
7884   pic16_freeAsmop (right,NULL,ic,TRUE);
7885   pic16_freeAsmop(left,NULL,ic,TRUE);
7886   pic16_freeAsmop(result,NULL,ic,TRUE);
7887 }
7888
7889 /*-----------------------------------------------------------------*/
7890 /* genrshOne - right shift a one byte quantity by known count      */
7891 /*-----------------------------------------------------------------*/
7892 static void genrshOne (operand *result, operand *left,
7893                        int shCount, int sign)
7894 {
7895     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7896     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7897 }
7898
7899 /*-----------------------------------------------------------------*/
7900 /* genrshTwo - right shift two bytes by known amount != 0          */
7901 /*-----------------------------------------------------------------*/
7902 static void genrshTwo (operand *result,operand *left,
7903                        int shCount, int sign)
7904 {
7905   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7906   /* if shCount >= 8 */
7907   if (shCount >= 8) {
7908     shCount -= 8 ;
7909     if (shCount)
7910       shiftR1Left2Result(left, MSB16, result, LSB,
7911                          shCount, sign);
7912     else
7913       movLeft2Result(left, MSB16, result, LSB);
7914
7915     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7916
7917     if(sign) {
7918       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7919       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7920     }
7921   }
7922
7923   /*  1 <= shCount <= 7 */
7924   else
7925     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7926 }
7927
7928 /*-----------------------------------------------------------------*/
7929 /* shiftRLong - shift right one long from left to result           */
7930 /* offl = LSB or MSB16                                             */
7931 /*-----------------------------------------------------------------*/
7932 static void shiftRLong (operand *left, int offl,
7933                         operand *result, int sign)
7934 {
7935     int size = AOP_SIZE(result);
7936     int same = pic16_sameRegs(AOP(left),AOP(result));
7937     int i;
7938     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7939
7940         if (same && (offl == MSB16)) { //shift one byte right
7941                 for(i=MSB16;i<size;i++) {
7942                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7943                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7944                 }
7945         }
7946
7947     if(sign)
7948                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7949         else
7950                 emitCLRC;
7951
7952         if (same) {
7953                 if (offl == LSB)
7954                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7955         } else {
7956         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7957         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7958         }
7959
7960     if(offl == MSB16) {
7961         /* add sign of "a" */
7962         pic16_addSign(result, MSB32, sign);
7963         }
7964
7965         if (same) {
7966         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7967         } else {
7968         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7969         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7970         }
7971         
7972         if (same) {
7973         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7974         } else {
7975         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7976         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7977         }
7978
7979         if (same) {
7980         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7981         } else {
7982         if(offl == LSB){
7983                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7984                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7985         }
7986         }
7987 }
7988
7989 /*-----------------------------------------------------------------*/
7990 /* genrshFour - shift four byte by a known amount != 0             */
7991 /*-----------------------------------------------------------------*/
7992 static void genrshFour (operand *result, operand *left,
7993                         int shCount, int sign)
7994 {
7995   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7996   /* if shifting more that 3 bytes */
7997   if(shCount >= 24 ) {
7998     shCount -= 24;
7999     if(shCount)
8000       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8001     else
8002       movLeft2Result(left, MSB32, result, LSB);
8003
8004     pic16_addSign(result, MSB16, sign);
8005   }
8006   else if(shCount >= 16){
8007     shCount -= 16;
8008     if(shCount)
8009       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8010     else{
8011       movLeft2Result(left, MSB24, result, LSB);
8012       movLeft2Result(left, MSB32, result, MSB16);
8013     }
8014     pic16_addSign(result, MSB24, sign);
8015   }
8016   else if(shCount >= 8){
8017     shCount -= 8;
8018     if(shCount == 1)
8019       shiftRLong(left, MSB16, result, sign);
8020     else if(shCount == 0){
8021       movLeft2Result(left, MSB16, result, LSB);
8022       movLeft2Result(left, MSB24, result, MSB16);
8023       movLeft2Result(left, MSB32, result, MSB24);
8024       pic16_addSign(result, MSB32, sign);
8025     }
8026     else{ //shcount >= 2
8027       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8028       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8029       /* the last shift is signed */
8030       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8031       pic16_addSign(result, MSB32, sign);
8032     }
8033   }
8034   else{   /* 1 <= shCount <= 7 */
8035     if(shCount <= 2){
8036       shiftRLong(left, LSB, result, sign);
8037       if(shCount == 2)
8038         shiftRLong(result, LSB, result, sign);
8039     }
8040     else{
8041       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8042       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8043       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8044     }
8045   }
8046 }
8047
8048 /*-----------------------------------------------------------------*/
8049 /* genRightShiftLiteral - right shifting by known count            */
8050 /*-----------------------------------------------------------------*/
8051 static void genRightShiftLiteral (operand *left,
8052                                   operand *right,
8053                                   operand *result,
8054                                   iCode *ic,
8055                                   int sign)
8056 {    
8057   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8058   int lsize,res_size;
8059
8060   pic16_freeAsmop(right,NULL,ic,TRUE);
8061
8062   pic16_aopOp(left,ic,FALSE);
8063   pic16_aopOp(result,ic,FALSE);
8064
8065   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8066
8067 #if VIEW_SIZE
8068   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8069                  AOP_SIZE(left));
8070 #endif
8071
8072   lsize = pic16_getDataSize(left);
8073   res_size = pic16_getDataSize(result);
8074   /* test the LEFT size !!! */
8075
8076   /* I suppose that the left size >= result size */
8077   if(shCount == 0){
8078     while(res_size--)
8079       movLeft2Result(left, lsize, result, res_size);
8080   }
8081
8082   else if(shCount >= (lsize * 8)){
8083
8084     if(res_size == 1) {
8085       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8086       if(sign) {
8087         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8088         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8089       }
8090     } else {
8091
8092       if(sign) {
8093         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8094         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8095         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8096         while(res_size--)
8097           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8098
8099       } else {
8100
8101         while(res_size--)
8102           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8103       }
8104     }
8105   } else {
8106
8107     switch (res_size) {
8108     case 1:
8109       genrshOne (result,left,shCount,sign);
8110       break;
8111
8112     case 2:
8113       genrshTwo (result,left,shCount,sign);
8114       break;
8115
8116     case 4:
8117       genrshFour (result,left,shCount,sign);
8118       break;
8119     default :
8120       break;
8121     }
8122
8123   }
8124
8125   pic16_freeAsmop(left,NULL,ic,TRUE);
8126   pic16_freeAsmop(result,NULL,ic,TRUE);
8127 }
8128
8129 /*-----------------------------------------------------------------*/
8130 /* genSignedRightShift - right shift of signed number              */
8131 /*-----------------------------------------------------------------*/
8132 static void genSignedRightShift (iCode *ic)
8133 {
8134   operand *right, *left, *result;
8135   int size, offset;
8136   //  char *l;
8137   symbol *tlbl, *tlbl1 ;
8138   pCodeOp *pctemp;
8139
8140   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8141
8142   /* we do it the hard way put the shift count in b
8143      and loop thru preserving the sign */
8144   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8145
8146   right = IC_RIGHT(ic);
8147   left  = IC_LEFT(ic);
8148   result = IC_RESULT(ic);
8149
8150   pic16_aopOp(right,ic,FALSE);  
8151   pic16_aopOp(left,ic,FALSE);
8152   pic16_aopOp(result,ic,FALSE);
8153
8154
8155   if ( AOP_TYPE(right) == AOP_LIT) {
8156     genRightShiftLiteral (left,right,result,ic,1);
8157     return ;
8158   }
8159   /* shift count is unknown then we have to form 
8160      a loop get the loop count in B : Note: we take
8161      only the lower order byte since shifting
8162      more that 32 bits make no sense anyway, ( the
8163      largest size of an object can be only 32 bits ) */  
8164
8165   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8166   //pic16_emitcode("inc","b");
8167   //pic16_freeAsmop (right,NULL,ic,TRUE);
8168   //pic16_aopOp(left,ic,FALSE);
8169   //pic16_aopOp(result,ic,FALSE);
8170
8171   /* now move the left to the result if they are not the
8172      same */
8173   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8174       AOP_SIZE(result) > 1) {
8175
8176     size = AOP_SIZE(result);
8177     offset=0;
8178     while (size--) { 
8179       /*
8180         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8181         if (*l == '@' && IS_AOP_PREG(result)) {
8182
8183         pic16_emitcode("mov","a,%s",l);
8184         pic16_aopPut(AOP(result),"a",offset);
8185         } else
8186         pic16_aopPut(AOP(result),l,offset);
8187       */
8188       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8189       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8190
8191       offset++;
8192     }
8193   }
8194
8195   /* mov the highest order bit to OVR */    
8196   tlbl = newiTempLabel(NULL);
8197   tlbl1= newiTempLabel(NULL);
8198
8199   size = AOP_SIZE(result);
8200   offset = size - 1;
8201
8202   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8203
8204   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8205
8206   /* offset should be 0, 1 or 3 */
8207   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8208   emitSKPNZ;
8209   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8210
8211   pic16_emitpcode(POC_MOVWF, pctemp);
8212
8213
8214   pic16_emitpLabel(tlbl->key);
8215
8216   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8217   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8218
8219   while(--size) {
8220     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8221   }
8222
8223   pic16_emitpcode(POC_DECFSZ,  pctemp);
8224   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8225   pic16_emitpLabel(tlbl1->key);
8226
8227   pic16_popReleaseTempReg(pctemp);
8228 #if 0
8229   size = AOP_SIZE(result);
8230   offset = size - 1;
8231   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8232   pic16_emitcode("rlc","a");
8233   pic16_emitcode("mov","ov,c");
8234   /* if it is only one byte then */
8235   if (size == 1) {
8236     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8237     MOVA(l);
8238     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8239     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8240     pic16_emitcode("mov","c,ov");
8241     pic16_emitcode("rrc","a");
8242     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8243     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8244     pic16_aopPut(AOP(result),"a",0);
8245     goto release ;
8246   }
8247
8248   reAdjustPreg(AOP(result));
8249   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8250   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8251   pic16_emitcode("mov","c,ov");
8252   while (size--) {
8253     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8254     MOVA(l);
8255     pic16_emitcode("rrc","a");         
8256     pic16_aopPut(AOP(result),"a",offset--);
8257   }
8258   reAdjustPreg(AOP(result));
8259   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8260   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8261
8262  release:
8263 #endif
8264
8265   pic16_freeAsmop(left,NULL,ic,TRUE);
8266   pic16_freeAsmop(result,NULL,ic,TRUE);
8267   pic16_freeAsmop(right,NULL,ic,TRUE);
8268 }
8269
8270 /*-----------------------------------------------------------------*/
8271 /* genRightShift - generate code for right shifting                */
8272 /*-----------------------------------------------------------------*/
8273 static void genRightShift (iCode *ic)
8274 {
8275     operand *right, *left, *result;
8276     sym_link *letype ;
8277     int size, offset;
8278     char *l;
8279     symbol *tlbl, *tlbl1 ;
8280
8281     /* if signed then we do it the hard way preserve the
8282     sign bit moving it inwards */
8283     letype = getSpec(operandType(IC_LEFT(ic)));
8284     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8285
8286     if (!SPEC_USIGN(letype)) {
8287         genSignedRightShift (ic);
8288         return ;
8289     }
8290
8291     /* signed & unsigned types are treated the same : i.e. the
8292     signed is NOT propagated inwards : quoting from the
8293     ANSI - standard : "for E1 >> E2, is equivalent to division
8294     by 2**E2 if unsigned or if it has a non-negative value,
8295     otherwise the result is implementation defined ", MY definition
8296     is that the sign does not get propagated */
8297
8298     right = IC_RIGHT(ic);
8299     left  = IC_LEFT(ic);
8300     result = IC_RESULT(ic);
8301
8302     pic16_aopOp(right,ic,FALSE);
8303
8304     /* if the shift count is known then do it 
8305     as efficiently as possible */
8306     if (AOP_TYPE(right) == AOP_LIT) {
8307         genRightShiftLiteral (left,right,result,ic, 0);
8308         return ;
8309     }
8310
8311     /* shift count is unknown then we have to form 
8312     a loop get the loop count in B : Note: we take
8313     only the lower order byte since shifting
8314     more that 32 bits make no sense anyway, ( the
8315     largest size of an object can be only 32 bits ) */  
8316
8317     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8318     pic16_emitcode("inc","b");
8319     pic16_aopOp(left,ic,FALSE);
8320     pic16_aopOp(result,ic,FALSE);
8321
8322     /* now move the left to the result if they are not the
8323     same */
8324     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8325         AOP_SIZE(result) > 1) {
8326
8327         size = AOP_SIZE(result);
8328         offset=0;
8329         while (size--) {
8330             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8331             if (*l == '@' && IS_AOP_PREG(result)) {
8332
8333                 pic16_emitcode("mov","a,%s",l);
8334                 pic16_aopPut(AOP(result),"a",offset);
8335             } else
8336                 pic16_aopPut(AOP(result),l,offset);
8337             offset++;
8338         }
8339     }
8340
8341     tlbl = newiTempLabel(NULL);
8342     tlbl1= newiTempLabel(NULL);
8343     size = AOP_SIZE(result);
8344     offset = size - 1;
8345
8346     /* if it is only one byte then */
8347     if (size == 1) {
8348
8349       tlbl = newiTempLabel(NULL);
8350       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8351         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8352         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8353       }
8354
8355       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8356       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8357       pic16_emitpLabel(tlbl->key);
8358       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8359       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8360       emitSKPC;
8361       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8362
8363       goto release ;
8364     }
8365
8366     reAdjustPreg(AOP(result));
8367     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8368     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8369     CLRC;
8370     while (size--) {
8371         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8372         MOVA(l);
8373         pic16_emitcode("rrc","a");         
8374         pic16_aopPut(AOP(result),"a",offset--);
8375     }
8376     reAdjustPreg(AOP(result));
8377
8378     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8379     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8380
8381 release:
8382     pic16_freeAsmop(left,NULL,ic,TRUE);
8383     pic16_freeAsmop (right,NULL,ic,TRUE);
8384     pic16_freeAsmop(result,NULL,ic,TRUE);
8385 }
8386
8387 /*-----------------------------------------------------------------*/
8388 /* genUnpackBits - generates code for unpacking bits               */
8389 /*-----------------------------------------------------------------*/
8390 static void genUnpackBits (operand *result, char *rname, int ptype)
8391 {    
8392     int shCnt ;
8393     int rlen = 0 ;
8394     sym_link *etype;
8395     int offset = 0 ;
8396
8397         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8398         etype = getSpec(operandType(result));
8399
8400         /* read the first byte  */
8401         switch (ptype) {
8402                 case POINTER:
8403                 case IPOINTER:
8404                 case PPOINTER:
8405                 case FPOINTER:
8406                 case GPOINTER:
8407                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8408                         break;
8409                 case CPOINTER:
8410                         pic16_emitcode("clr","a");
8411                         pic16_emitcode("movc","a","@a+dptr");
8412                         break;
8413         }
8414         
8415
8416         /* if we have bitdisplacement then it fits   */
8417         /* into this byte completely or if length is */
8418         /* less than a byte                          */
8419         if ((shCnt = SPEC_BSTR(etype)) || 
8420                 (SPEC_BLEN(etype) <= 8))  {
8421
8422                 /* shift right acc */
8423                 AccRsh(shCnt, 0);
8424
8425                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8426                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8427
8428 /* VR -- normally I would use the following, but since we use the hack,
8429  * to avoid the masking from AccRsh, why not mask it right now? */
8430
8431 /*
8432                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8433 */
8434
8435                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8436           return ;
8437         }
8438
8439
8440
8441         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8442         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8443         exit(-1);
8444
8445     /* bit field did not fit in a byte  */
8446     rlen = SPEC_BLEN(etype) - 8;
8447     pic16_aopPut(AOP(result),"a",offset++);
8448
8449     while (1)  {
8450
8451         switch (ptype) {
8452         case POINTER:
8453         case IPOINTER:
8454             pic16_emitcode("inc","%s",rname);
8455             pic16_emitcode("mov","a,@%s",rname);
8456             break;
8457             
8458         case PPOINTER:
8459             pic16_emitcode("inc","%s",rname);
8460             pic16_emitcode("movx","a,@%s",rname);
8461             break;
8462
8463         case FPOINTER:
8464             pic16_emitcode("inc","dptr");
8465             pic16_emitcode("movx","a,@dptr");
8466             break;
8467             
8468         case CPOINTER:
8469             pic16_emitcode("clr","a");
8470             pic16_emitcode("inc","dptr");
8471             pic16_emitcode("movc","a","@a+dptr");
8472             break;
8473             
8474         case GPOINTER:
8475             pic16_emitcode("inc","dptr");
8476             pic16_emitcode("lcall","__gptrget");
8477             break;
8478         }
8479
8480         rlen -= 8;            
8481         /* if we are done */
8482         if ( rlen <= 0 )
8483             break ;
8484         
8485         pic16_aopPut(AOP(result),"a",offset++);
8486                               
8487     }
8488     
8489     if (rlen) {
8490         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8491         pic16_aopPut(AOP(result),"a",offset);          
8492     }
8493     
8494     return ;
8495 }
8496
8497
8498 static void genDataPointerGet(operand *left,
8499                               operand *result,
8500                               iCode *ic)
8501 {
8502   int size, offset = 0, leoffset=0 ;
8503
8504         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8505         pic16_aopOp(result, ic, FALSE);
8506
8507         size = AOP_SIZE(result);
8508 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8509
8510
8511 #if 0
8512         /* The following tests may save a redudant movff instruction when
8513          * accessing unions */
8514          
8515         /* if they are the same */
8516         if (operandsEqu (left, result)) {
8517                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8518                 goto release;
8519         }
8520
8521         /* if they are the same registers */
8522         if (pic16_sameRegs(AOP(left),AOP(result))) {
8523                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8524                 goto release;
8525         }
8526 #endif
8527
8528 #if 0
8529         if ( AOP_TYPE(left) == AOP_PCODE) {
8530                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
8531                                 AOP(left)->aopu.pcop->name,
8532                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
8533                                 PCOR(AOP(left)->aopu.pcop)->instance:
8534                                 PCOI(AOP(left)->aopu.pcop)->offset);
8535         }
8536 #endif
8537
8538         if(AOP(left)->aopu.pcop->type == PO_DIR)
8539                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8540
8541         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8542
8543         while (size--) {
8544                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8545                 
8546                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8547                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8548                         mov2w(AOP(left), leoffset);
8549                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8550                 } else {
8551                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8552                                 pic16_popGet(AOP(left), leoffset),
8553                                 pic16_popGet(AOP(result), offset)));
8554                 }
8555
8556                 offset++;
8557                 leoffset++;
8558         }
8559
8560 //release:
8561     pic16_freeAsmop(result,NULL,ic,TRUE);
8562 }
8563
8564 void pic16_loadFSR0(operand *op)
8565 {
8566         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8567 }
8568
8569
8570 /*-----------------------------------------------------------------*/
8571 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8572 /*-----------------------------------------------------------------*/
8573 static void genNearPointerGet (operand *left, 
8574                                operand *result, 
8575                                iCode *ic)
8576 {
8577     asmop *aop = NULL;
8578     //regs *preg = NULL ;
8579     sym_link *rtype, *retype;
8580     sym_link *ltype = operandType(left);    
8581
8582         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8583
8584         rtype = operandType(result);
8585         retype= getSpec(rtype);
8586     
8587         pic16_aopOp(left,ic,FALSE);
8588
8589         /* if left is rematerialisable and
8590          * result is not bit variable type and
8591          * the left is pointer to data space i.e
8592          * lower 128 bytes of space */
8593         if (AOP_TYPE(left) == AOP_PCODE
8594                 && !IS_BITFIELD(retype)
8595                 && DCL_TYPE(ltype) == POINTER) {
8596
8597                 genDataPointerGet (left,result,ic);
8598                 pic16_freeAsmop(left, NULL, ic, TRUE);
8599           return ;
8600         }
8601     
8602         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8603
8604         /* if the value is already in a pointer register
8605          * then don't need anything more */
8606         if (!AOP_INPREG(AOP(left))) {
8607                 /* otherwise get a free pointer register */
8608                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8609                 
8610                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
8611                 pic16_loadFSR0( left );
8612         }
8613 //       else
8614 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8615     
8616     pic16_aopOp (result,ic,FALSE);
8617     
8618       /* if bitfield then unpack the bits */
8619     if (IS_BITFIELD(retype)) 
8620         genUnpackBits (result, NULL, POINTER);
8621     else {
8622         /* we have can just get the values */
8623       int size = AOP_SIZE(result);
8624       int offset = 0;   
8625         
8626       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8627
8628
8629         /* fsr0 is loaded already -- VR */
8630 //      pic16_loadFSR0( left );
8631
8632 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8633 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8634       while(size--) {
8635
8636         if(size) {
8637                 pic16_emitpcode(POC_MOVFF,
8638                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8639                                 pic16_popGet(AOP(result), offset++)));
8640         } else {
8641                 pic16_emitpcode(POC_MOVFF,
8642                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8643                                 pic16_popGet(AOP(result), offset++)));
8644         }
8645       }
8646 #if 0
8647 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
8648 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8649         if(size)
8650           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8651 #endif
8652 /*
8653         while (size--) {
8654             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8655
8656                 pic16_emitcode("mov","a,@%s",rname);
8657                 pic16_aopPut(AOP(result),"a",offset);
8658             } else {
8659                 sprintf(buffer,"@%s",rname);
8660                 pic16_aopPut(AOP(result),buffer,offset);
8661             }
8662             offset++ ;
8663             if (size)
8664                 pic16_emitcode("inc","%s",rname);
8665         }
8666 */
8667     }
8668
8669     /* now some housekeeping stuff */
8670     if (aop) {
8671         /* we had to allocate for this iCode */
8672     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8673         pic16_freeAsmop(NULL,aop,ic,TRUE);
8674     } else { 
8675         /* we did not allocate which means left
8676            already in a pointer register, then
8677            if size > 0 && this could be used again
8678            we have to point it back to where it 
8679            belongs */
8680     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8681         if (AOP_SIZE(result) > 1 &&
8682             !OP_SYMBOL(left)->remat &&
8683             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8684               ic->depth )) {
8685 //          int size = AOP_SIZE(result) - 1;
8686 //          while (size--)
8687 //              pic16_emitcode("dec","%s",rname);
8688         }
8689     }
8690
8691     /* done */
8692     pic16_freeAsmop(left,NULL,ic,TRUE);
8693     pic16_freeAsmop(result,NULL,ic,TRUE);
8694      
8695 }
8696
8697 /*-----------------------------------------------------------------*/
8698 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8699 /*-----------------------------------------------------------------*/
8700 static void genPagedPointerGet (operand *left, 
8701                                operand *result, 
8702                                iCode *ic)
8703 {
8704     asmop *aop = NULL;
8705     regs *preg = NULL ;
8706     char *rname ;
8707     sym_link *rtype, *retype;    
8708
8709     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8710
8711     rtype = operandType(result);
8712     retype= getSpec(rtype);
8713     
8714     pic16_aopOp(left,ic,FALSE);
8715
8716   /* if the value is already in a pointer register
8717        then don't need anything more */
8718     if (!AOP_INPREG(AOP(left))) {
8719         /* otherwise get a free pointer register */
8720         aop = newAsmop(0);
8721         preg = getFreePtr(ic,&aop,FALSE);
8722         pic16_emitcode("mov","%s,%s",
8723                 preg->name,
8724                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8725         rname = preg->name ;
8726     } else
8727         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8728     
8729     pic16_freeAsmop(left,NULL,ic,TRUE);
8730     pic16_aopOp (result,ic,FALSE);
8731
8732     /* if bitfield then unpack the bits */
8733     if (IS_BITFIELD(retype)) 
8734         genUnpackBits (result,rname,PPOINTER);
8735     else {
8736         /* we have can just get the values */
8737         int size = AOP_SIZE(result);
8738         int offset = 0 ;        
8739         
8740         while (size--) {
8741             
8742             pic16_emitcode("movx","a,@%s",rname);
8743             pic16_aopPut(AOP(result),"a",offset);
8744             
8745             offset++ ;
8746             
8747             if (size)
8748                 pic16_emitcode("inc","%s",rname);
8749         }
8750     }
8751
8752     /* now some housekeeping stuff */
8753     if (aop) {
8754         /* we had to allocate for this iCode */
8755         pic16_freeAsmop(NULL,aop,ic,TRUE);
8756     } else { 
8757         /* we did not allocate which means left
8758            already in a pointer register, then
8759            if size > 0 && this could be used again
8760            we have to point it back to where it 
8761            belongs */
8762         if (AOP_SIZE(result) > 1 &&
8763             !OP_SYMBOL(left)->remat &&
8764             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8765               ic->depth )) {
8766             int size = AOP_SIZE(result) - 1;
8767             while (size--)
8768                 pic16_emitcode("dec","%s",rname);
8769         }
8770     }
8771
8772     /* done */
8773     pic16_freeAsmop(result,NULL,ic,TRUE);
8774     
8775         
8776 }
8777
8778 /*-----------------------------------------------------------------*/
8779 /* genFarPointerGet - gget value from far space                    */
8780 /*-----------------------------------------------------------------*/
8781 static void genFarPointerGet (operand *left,
8782                               operand *result, iCode *ic)
8783 {
8784     int size, offset ;
8785     sym_link *retype = getSpec(operandType(result));
8786
8787     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8788
8789     pic16_aopOp(left,ic,FALSE);
8790
8791     /* if the operand is already in dptr 
8792     then we do nothing else we move the value to dptr */
8793     if (AOP_TYPE(left) != AOP_STR) {
8794         /* if this is remateriazable */
8795         if (AOP_TYPE(left) == AOP_IMMD)
8796             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8797         else { /* we need to get it byte by byte */
8798             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8799             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8800             if (options.model == MODEL_FLAT24)
8801             {
8802                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8803             }
8804         }
8805     }
8806     /* so dptr know contains the address */
8807     pic16_freeAsmop(left,NULL,ic,TRUE);
8808     pic16_aopOp(result,ic,FALSE);
8809
8810     /* if bit then unpack */
8811     if (IS_BITFIELD(retype)) 
8812         genUnpackBits(result,"dptr",FPOINTER);
8813     else {
8814         size = AOP_SIZE(result);
8815         offset = 0 ;
8816
8817         while (size--) {
8818             pic16_emitcode("movx","a,@dptr");
8819             pic16_aopPut(AOP(result),"a",offset++);
8820             if (size)
8821                 pic16_emitcode("inc","dptr");
8822         }
8823     }
8824
8825     pic16_freeAsmop(result,NULL,ic,TRUE);
8826 }
8827 #if 0
8828 /*-----------------------------------------------------------------*/
8829 /* genCodePointerGet - get value from code space                  */
8830 /*-----------------------------------------------------------------*/
8831 static void genCodePointerGet (operand *left,
8832                                 operand *result, iCode *ic)
8833 {
8834     int size, offset ;
8835     sym_link *retype = getSpec(operandType(result));
8836
8837     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8838
8839     pic16_aopOp(left,ic,FALSE);
8840
8841     /* if the operand is already in dptr 
8842     then we do nothing else we move the value to dptr */
8843     if (AOP_TYPE(left) != AOP_STR) {
8844         /* if this is remateriazable */
8845         if (AOP_TYPE(left) == AOP_IMMD)
8846             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8847         else { /* we need to get it byte by byte */
8848             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8849             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8850             if (options.model == MODEL_FLAT24)
8851             {
8852                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8853             }
8854         }
8855     }
8856     /* so dptr know contains the address */
8857     pic16_freeAsmop(left,NULL,ic,TRUE);
8858     pic16_aopOp(result,ic,FALSE);
8859
8860     /* if bit then unpack */
8861     if (IS_BITFIELD(retype)) 
8862         genUnpackBits(result,"dptr",CPOINTER);
8863     else {
8864         size = AOP_SIZE(result);
8865         offset = 0 ;
8866
8867         while (size--) {
8868             pic16_emitcode("clr","a");
8869             pic16_emitcode("movc","a,@a+dptr");
8870             pic16_aopPut(AOP(result),"a",offset++);
8871             if (size)
8872                 pic16_emitcode("inc","dptr");
8873         }
8874     }
8875
8876     pic16_freeAsmop(result,NULL,ic,TRUE);
8877 }
8878 #endif
8879 /*-----------------------------------------------------------------*/
8880 /* genGenPointerGet - gget value from generic pointer space        */
8881 /*-----------------------------------------------------------------*/
8882 static void genGenPointerGet (operand *left,
8883                               operand *result, iCode *ic)
8884 {
8885   int size, offset, lit;
8886   sym_link *retype = getSpec(operandType(result));
8887
8888         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8889         pic16_aopOp(left,ic,FALSE);
8890         pic16_aopOp(result,ic,FALSE);
8891         size = AOP_SIZE(result);
8892
8893         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8894
8895         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
8896
8897                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
8898                 // load FSR0 from immediate
8899                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8900
8901 //              pic16_loadFSR0( left );
8902
8903                 offset = 0;
8904                 while(size--) {
8905                         if(size) {
8906                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8907                         } else {
8908                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8909                         }
8910                         offset++;
8911                 }
8912                 goto release;
8913
8914         }
8915         else { /* we need to get it byte by byte */
8916                 // set up FSR0 with address from left
8917                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
8918                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
8919
8920                 offset = 0 ;
8921
8922                 while(size--) {
8923                         if(size) {
8924                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8925                         } else {
8926                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8927                         }
8928                         offset++;
8929                 }
8930                 goto release;
8931         }
8932
8933   /* if bit then unpack */
8934         if (IS_BITFIELD(retype)) 
8935                 genUnpackBits(result,"BAD",GPOINTER);
8936
8937         release:
8938         pic16_freeAsmop(left,NULL,ic,TRUE);
8939         pic16_freeAsmop(result,NULL,ic,TRUE);
8940
8941 }
8942
8943 /*-----------------------------------------------------------------*/
8944 /* genConstPointerGet - get value from const generic pointer space */
8945 /*-----------------------------------------------------------------*/
8946 static void genConstPointerGet (operand *left,
8947                                 operand *result, iCode *ic)
8948 {
8949   //sym_link *retype = getSpec(operandType(result));
8950   symbol *albl = newiTempLabel(NULL);
8951   symbol *blbl = newiTempLabel(NULL);
8952   PIC_OPCODE poc;
8953
8954   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8955   pic16_aopOp(left,ic,FALSE);
8956   pic16_aopOp(result,ic,FALSE);
8957
8958
8959   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8960
8961   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8962
8963   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8964   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8965   pic16_emitpLabel(albl->key);
8966
8967   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8968     
8969   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8970   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8971   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8972   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8973   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8974
8975   pic16_emitpLabel(blbl->key);
8976
8977   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8978
8979
8980   pic16_freeAsmop(left,NULL,ic,TRUE);
8981   pic16_freeAsmop(result,NULL,ic,TRUE);
8982
8983 }
8984 /*-----------------------------------------------------------------*/
8985 /* genPointerGet - generate code for pointer get                   */
8986 /*-----------------------------------------------------------------*/
8987 static void genPointerGet (iCode *ic)
8988 {
8989     operand *left, *result ;
8990     sym_link *type, *etype;
8991     int p_type;
8992
8993     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8994
8995     left = IC_LEFT(ic);
8996     result = IC_RESULT(ic) ;
8997
8998     /* depending on the type of pointer we need to
8999     move it to the correct pointer register */
9000     type = operandType(left);
9001     etype = getSpec(type);
9002
9003 #if 0
9004     if (IS_PTR_CONST(type))
9005 #else
9006     if (IS_CODEPTR(type))
9007 #endif
9008       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9009
9010     /* if left is of type of pointer then it is simple */
9011     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9012         p_type = DCL_TYPE(type);
9013     else {
9014         /* we have to go by the storage class */
9015         p_type = PTR_TYPE(SPEC_OCLS(etype));
9016
9017         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9018
9019         if (SPEC_OCLS(etype)->codesp ) {
9020           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9021           //p_type = CPOINTER ; 
9022         }
9023         else
9024             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9025               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9026                /*p_type = FPOINTER ;*/ 
9027             else
9028                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9029                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9030 /*                  p_type = PPOINTER; */
9031                 else
9032                     if (SPEC_OCLS(etype) == idata )
9033                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9034 /*                      p_type = IPOINTER; */
9035                     else
9036                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9037 /*                      p_type = POINTER ; */
9038     }
9039
9040     /* now that we have the pointer type we assign
9041     the pointer values */
9042     switch (p_type) {
9043
9044     case POINTER:       
9045     case IPOINTER:
9046         genNearPointerGet (left,result,ic);
9047         break;
9048
9049     case PPOINTER:
9050         genPagedPointerGet(left,result,ic);
9051         break;
9052
9053     case FPOINTER:
9054         genFarPointerGet (left,result,ic);
9055         break;
9056
9057     case CPOINTER:
9058         genConstPointerGet (left,result,ic);
9059         //pic16_emitcodePointerGet (left,result,ic);
9060         break;
9061
9062     case GPOINTER:
9063 #if 0
9064       if (IS_PTR_CONST(type))
9065         genConstPointerGet (left,result,ic);
9066       else
9067 #endif
9068         genGenPointerGet (left,result,ic);
9069       break;
9070     }
9071
9072 }
9073
9074 /*-----------------------------------------------------------------*/
9075 /* genPackBits - generates code for packed bit storage             */
9076 /*-----------------------------------------------------------------*/
9077 static void genPackBits (sym_link    *etype ,
9078                          operand *right ,
9079                          char *rname, int p_type)
9080 {
9081   int shCnt = 0 ;
9082   int offset = 0  ;
9083   int rLen = 0 ;
9084   int blen, bstr ;   
9085   char *l ;
9086
9087         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9088         blen = SPEC_BLEN(etype);
9089         bstr = SPEC_BSTR(etype);
9090
9091         if(AOP_TYPE(right) == AOP_LIT) {
9092                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9093                 offset++;
9094         } else
9095                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9096
9097 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9098         MOVA(l);   
9099 */
9100         /* if the bit lenth is less than or    */
9101         /* it exactly fits a byte then         */
9102         if((shCnt=SPEC_BSTR(etype))
9103                 || SPEC_BLEN(etype) <= 8 )  {
9104
9105                 /* shift left acc */
9106                 AccLsh(shCnt);
9107
9108                 /* using PRODL as a temporary register here */
9109                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9110
9111                 switch (p_type) {
9112                         case FPOINTER:
9113                         case POINTER:
9114                         case GPOINTER:
9115                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9116 //                              pic16_emitcode ("mov","b,a");
9117 //                              pic16_emitcode("mov","a,@%s",rname);
9118                                 break;
9119                 }
9120 #if 1
9121                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9122                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9123                                         (unsigned char)(0xff >> (8-bstr))) ));
9124                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9125                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9126 #endif
9127
9128 #if 0
9129                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9130                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9131                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9132                 pic16_emitcode ("orl","a,b");
9133                 if (p_type == GPOINTER)
9134                         pic16_emitcode("pop","b");
9135
9136                 
9137                 switch (p_type) {
9138                         case POINTER:
9139                                 pic16_emitcode("mov","@%s,a",rname);
9140                                 break;
9141                         case FPOINTER:
9142                                 pic16_emitcode("movx","@dptr,a");
9143                                 break;
9144                         case GPOINTER:
9145                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9146                                 break;
9147                 }
9148 #endif
9149
9150           return;
9151         }
9152
9153
9154         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9155         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9156         exit(-1);
9157
9158
9159     /* if we r done */
9160     if ( SPEC_BLEN(etype) <= 8 )
9161         return ;
9162
9163     pic16_emitcode("inc","%s",rname);
9164     rLen = SPEC_BLEN(etype) ;     
9165
9166
9167
9168     /* now generate for lengths greater than one byte */
9169     while (1) {
9170
9171         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9172
9173         rLen -= 8 ;
9174         if (rLen <= 0 )
9175             break ;
9176
9177         switch (p_type) {
9178             case POINTER:
9179                 if (*l == '@') {
9180                     MOVA(l);
9181                     pic16_emitcode("mov","@%s,a",rname);
9182                 } else
9183                     pic16_emitcode("mov","@%s,%s",rname,l);
9184                 break;
9185
9186             case FPOINTER:
9187                 MOVA(l);
9188                 pic16_emitcode("movx","@dptr,a");
9189                 break;
9190
9191             case GPOINTER:
9192                 MOVA(l);
9193                 DEBUGpic16_emitcode(";lcall","__gptrput");
9194                 break;  
9195         }   
9196         pic16_emitcode ("inc","%s",rname);
9197     }
9198
9199     MOVA(l);
9200
9201     /* last last was not complete */
9202     if (rLen)   {
9203         /* save the byte & read byte */
9204         switch (p_type) {
9205             case POINTER:
9206                 pic16_emitcode ("mov","b,a");
9207                 pic16_emitcode("mov","a,@%s",rname);
9208                 break;
9209
9210             case FPOINTER:
9211                 pic16_emitcode ("mov","b,a");
9212                 pic16_emitcode("movx","a,@dptr");
9213                 break;
9214
9215             case GPOINTER:
9216                 pic16_emitcode ("push","b");
9217                 pic16_emitcode ("push","acc");
9218                 pic16_emitcode ("lcall","__gptrget");
9219                 pic16_emitcode ("pop","b");
9220                 break;
9221         }
9222
9223         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9224         pic16_emitcode ("orl","a,b");
9225     }
9226
9227     if (p_type == GPOINTER)
9228         pic16_emitcode("pop","b");
9229
9230     switch (p_type) {
9231
9232     case POINTER:
9233         pic16_emitcode("mov","@%s,a",rname);
9234         break;
9235         
9236     case FPOINTER:
9237         pic16_emitcode("movx","@dptr,a");
9238         break;
9239         
9240     case GPOINTER:
9241         DEBUGpic16_emitcode(";lcall","__gptrput");
9242         break;                  
9243     }
9244 }
9245 /*-----------------------------------------------------------------*/
9246 /* genDataPointerSet - remat pointer to data space                 */
9247 /*-----------------------------------------------------------------*/
9248 static void genDataPointerSet(operand *right,
9249                               operand *result,
9250                               iCode *ic)
9251 {
9252     int size, offset = 0, resoffset=0 ;
9253
9254     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9255     pic16_aopOp(right,ic,FALSE);
9256
9257     size = AOP_SIZE(right);
9258         fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9259
9260 #if 1
9261     if ( AOP_TYPE(result) == AOP_PCODE) {
9262       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9263               AOP(result)->aopu.pcop->name,
9264                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9265               PCOR(AOP(result)->aopu.pcop)->instance:
9266               PCOI(AOP(result)->aopu.pcop)->offset);
9267     }
9268 #endif
9269
9270         if(AOP(result)->aopu.pcop->type == PO_DIR)
9271                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9272
9273         while (size--) {
9274                 if (AOP_TYPE(right) == AOP_LIT) {
9275                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9276
9277                         lit = lit >> (8*offset);
9278                         if(lit&0xff) {
9279                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9280                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),resoffset));
9281                         } else {
9282                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),resoffset));
9283                         }
9284                 } else {
9285                         mov2w(AOP(right), offset);
9286                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),resoffset));
9287                 }
9288                 offset++;
9289                 resoffset++;
9290         }
9291
9292     pic16_freeAsmop(right,NULL,ic,TRUE);
9293 }
9294
9295
9296
9297 /*-----------------------------------------------------------------*/
9298 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9299 /*-----------------------------------------------------------------*/
9300 static void genNearPointerSet (operand *right,
9301                                operand *result, 
9302                                iCode *ic)
9303 {
9304   asmop *aop = NULL;
9305   char *l;
9306   sym_link *retype;
9307   sym_link *ptype = operandType(result);
9308   sym_link *resetype;
9309     
9310         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9311         retype= getSpec(operandType(right));
9312         resetype = getSpec(operandType(result));
9313   
9314         pic16_aopOp(result,ic,FALSE);
9315     
9316         /* if the result is rematerializable &
9317          * in data space & not a bit variable */
9318         
9319         /* and result is not a bit variable */
9320         if (AOP_TYPE(result) == AOP_PCODE
9321 //              && AOP_TYPE(result) == AOP_IMMD
9322                 && DCL_TYPE(ptype) == POINTER
9323                 && !IS_BITFIELD(retype)
9324                 && !IS_BITFIELD(resetype)) {
9325
9326                 genDataPointerSet (right,result,ic);
9327                 pic16_freeAsmop(result,NULL,ic,TRUE);
9328           return;
9329         }
9330
9331         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9332         pic16_aopOp(right,ic,FALSE);
9333         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9334
9335         /* if the value is already in a pointer register
9336          * then don't need anything more */
9337         if (!AOP_INPREG(AOP(result))) {
9338                 /* otherwise get a free pointer register */
9339                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9340
9341                 pic16_loadFSR0( result );
9342         }
9343 //      else
9344 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9345
9346         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9347
9348         /* if bitfield then unpack the bits */
9349         if (IS_BITFIELD(resetype)) {
9350                 genPackBits (resetype, right, NULL, POINTER);
9351         } else {
9352                 /* we have can just get the values */
9353           int size = AOP_SIZE(right);
9354           int offset = 0 ;    
9355
9356                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9357                 while (size--) {
9358                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9359                         if (*l == '@' ) {
9360                                 //MOVA(l);
9361                                 //pic16_emitcode("mov","@%s,a",rname);
9362                                 pic16_emitcode("movf","indf0,w ;1");
9363                         } else {
9364
9365                                 if (AOP_TYPE(right) == AOP_LIT) {
9366                                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9367
9368                                         if(lit) {
9369                                                 pic16_emitcode("movlw","%s",l);
9370                                                 pic16_emitcode("movwf","indf0 ;2");
9371                                         } else 
9372                                                 pic16_emitcode("clrf","indf0");
9373                                 } else {
9374                                         pic16_emitcode("movf","%s,w",l);
9375                                         pic16_emitcode("movwf","indf0 ;2");
9376                                 }
9377                                 //pic16_emitcode("mov","@%s,%s",rname,l);
9378                         }
9379                         if (size)
9380                                 pic16_emitcode("incf","fsr0,f ;3");
9381                         //pic16_emitcode("inc","%s",rname);
9382                         offset++;
9383                 }
9384         }
9385
9386         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9387         /* now some housekeeping stuff */
9388         if (aop) {
9389                 /* we had to allocate for this iCode */
9390                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9391         } else { 
9392                 /* we did not allocate which means left
9393                  * already in a pointer register, then
9394                  * if size > 0 && this could be used again
9395                  * we have to point it back to where it 
9396                  * belongs */
9397                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9398                 if (AOP_SIZE(right) > 1
9399                         && !OP_SYMBOL(result)->remat
9400                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9401                                 || ic->depth )) {
9402
9403                   int size = AOP_SIZE(right) - 1;
9404
9405                         while (size--)
9406                                 pic16_emitcode("decf","fsr0,f");
9407                         //pic16_emitcode("dec","%s",rname);
9408                 }
9409         }
9410
9411         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9412         /* done */
9413 //release:
9414         pic16_freeAsmop(right,NULL,ic,TRUE);
9415         pic16_freeAsmop(result,NULL,ic,TRUE);
9416 }
9417
9418 /*-----------------------------------------------------------------*/
9419 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9420 /*-----------------------------------------------------------------*/
9421 static void genPagedPointerSet (operand *right,
9422                                operand *result, 
9423                                iCode *ic)
9424 {
9425     asmop *aop = NULL;
9426     regs *preg = NULL ;
9427     char *rname , *l;
9428     sym_link *retype;
9429        
9430     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9431
9432     retype= getSpec(operandType(right));
9433     
9434     pic16_aopOp(result,ic,FALSE);
9435     
9436     /* if the value is already in a pointer register
9437        then don't need anything more */
9438     if (!AOP_INPREG(AOP(result))) {
9439         /* otherwise get a free pointer register */
9440         aop = newAsmop(0);
9441         preg = getFreePtr(ic,&aop,FALSE);
9442         pic16_emitcode("mov","%s,%s",
9443                 preg->name,
9444                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9445         rname = preg->name ;
9446     } else
9447         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9448     
9449     pic16_freeAsmop(result,NULL,ic,TRUE);
9450     pic16_aopOp (right,ic,FALSE);
9451
9452     /* if bitfield then unpack the bits */
9453     if (IS_BITFIELD(retype)) 
9454         genPackBits (retype,right,rname,PPOINTER);
9455     else {
9456         /* we have can just get the values */
9457         int size = AOP_SIZE(right);
9458         int offset = 0 ;        
9459         
9460         while (size--) {
9461             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9462             
9463             MOVA(l);
9464             pic16_emitcode("movx","@%s,a",rname);
9465
9466             if (size)
9467                 pic16_emitcode("inc","%s",rname);
9468
9469             offset++;
9470         }
9471     }
9472     
9473     /* now some housekeeping stuff */
9474     if (aop) {
9475         /* we had to allocate for this iCode */
9476         pic16_freeAsmop(NULL,aop,ic,TRUE);
9477     } else { 
9478         /* we did not allocate which means left
9479            already in a pointer register, then
9480            if size > 0 && this could be used again
9481            we have to point it back to where it 
9482            belongs */
9483         if (AOP_SIZE(right) > 1 &&
9484             !OP_SYMBOL(result)->remat &&
9485             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9486               ic->depth )) {
9487             int size = AOP_SIZE(right) - 1;
9488             while (size--)
9489                 pic16_emitcode("dec","%s",rname);
9490         }
9491     }
9492
9493     /* done */
9494     pic16_freeAsmop(right,NULL,ic,TRUE);
9495     
9496         
9497 }
9498
9499 /*-----------------------------------------------------------------*/
9500 /* genFarPointerSet - set value from far space                     */
9501 /*-----------------------------------------------------------------*/
9502 static void genFarPointerSet (operand *right,
9503                               operand *result, iCode *ic)
9504 {
9505     int size, offset ;
9506     sym_link *retype = getSpec(operandType(right));
9507
9508     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9509     pic16_aopOp(result,ic,FALSE);
9510
9511     /* if the operand is already in dptr 
9512     then we do nothing else we move the value to dptr */
9513     if (AOP_TYPE(result) != AOP_STR) {
9514         /* if this is remateriazable */
9515         if (AOP_TYPE(result) == AOP_IMMD)
9516             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9517         else { /* we need to get it byte by byte */
9518             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9519             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9520             if (options.model == MODEL_FLAT24)
9521             {
9522                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9523             }
9524         }
9525     }
9526     /* so dptr know contains the address */
9527     pic16_freeAsmop(result,NULL,ic,TRUE);
9528     pic16_aopOp(right,ic,FALSE);
9529
9530     /* if bit then unpack */
9531     if (IS_BITFIELD(retype)) 
9532         genPackBits(retype,right,"dptr",FPOINTER);
9533     else {
9534         size = AOP_SIZE(right);
9535         offset = 0 ;
9536
9537         while (size--) {
9538             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9539             MOVA(l);
9540             pic16_emitcode("movx","@dptr,a");
9541             if (size)
9542                 pic16_emitcode("inc","dptr");
9543         }
9544     }
9545
9546     pic16_freeAsmop(right,NULL,ic,TRUE);
9547 }
9548
9549 /*-----------------------------------------------------------------*/
9550 /* genGenPointerSet - set value from generic pointer space         */
9551 /*-----------------------------------------------------------------*/
9552 static void genGenPointerSet (operand *right,
9553                               operand *result, iCode *ic)
9554 {
9555         int size, offset, lit;
9556         sym_link *retype = getSpec(operandType(right));
9557
9558         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9559
9560         pic16_aopOp(result,ic,FALSE);
9561         pic16_aopOp(right,ic,FALSE);
9562         size = AOP_SIZE(right);
9563         offset = 0;
9564
9565         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9566
9567         /* if the operand is already in dptr 
9568                 then we do nothing else we move the value to dptr */
9569         if (AOP_TYPE(result) != AOP_STR) {
9570                 /* if this is remateriazable */
9571                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9572                 // WARNING: anythig until "else" is untested!
9573                 if (AOP_TYPE(result) == AOP_IMMD) {
9574                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9575                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9576                         // load FSR0 from immediate
9577                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9578                         offset = 0;
9579                         while(size--) {
9580                                 if(size) {
9581                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9582                                 } else {
9583                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9584                                 }
9585                                 offset++;
9586                         }
9587                         goto release;
9588                 }
9589                 else { /* we need to get it byte by byte */
9590                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9591                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9592
9593                         // set up FSR0 with address of result
9594                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9595                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9596
9597                         /* hack hack! see if this the FSR. If so don't load W */
9598                         if(AOP_TYPE(right) != AOP_ACC) {
9599
9600                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9601
9602                                 while(size--) {
9603                                         if(size) {
9604                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9605                                         } else {
9606                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9607                                         }
9608                                         offset++;
9609                                 }
9610                                 goto release;
9611                         } 
9612                         // right = ACC
9613                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9614                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9615                         goto release;
9616         } // if (AOP_TYPE(result) != AOP_IMMD)
9617
9618         } // if (AOP_TYPE(result) != AOP_STR)
9619         /* so dptr know contains the address */
9620
9621
9622         /* if bit then unpack */
9623         if (IS_BITFIELD(retype)) 
9624                 genPackBits(retype,right,"dptr",GPOINTER);
9625         else {
9626                 size = AOP_SIZE(right);
9627                 offset = 0 ;
9628
9629                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9630
9631                 // set up FSR0 with address of result
9632                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9633                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9634         
9635                 while (size--) {
9636                         if (AOP_TYPE(right) == AOP_LIT) {
9637                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9638                                 if (size) {
9639                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9640                                 } else {
9641                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9642                                 }
9643                         } else { // no literal
9644                                 if(size) {
9645                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9646                                 } else {
9647                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9648                                 }
9649                         }
9650                         offset++;
9651         }
9652         }
9653
9654         release:
9655         pic16_freeAsmop(right,NULL,ic,TRUE);
9656         pic16_freeAsmop(result,NULL,ic,TRUE);
9657 }
9658
9659 /*-----------------------------------------------------------------*/
9660 /* genPointerSet - stores the value into a pointer location        */
9661 /*-----------------------------------------------------------------*/
9662 static void genPointerSet (iCode *ic)
9663 {    
9664     operand *right, *result ;
9665     sym_link *type, *etype;
9666     int p_type;
9667
9668     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9669
9670     right = IC_RIGHT(ic);
9671     result = IC_RESULT(ic) ;
9672
9673     /* depending on the type of pointer we need to
9674     move it to the correct pointer register */
9675     type = operandType(result);
9676     etype = getSpec(type);
9677     /* if left is of type of pointer then it is simple */
9678     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9679         p_type = DCL_TYPE(type);
9680     }
9681     else {
9682         /* we have to go by the storage class */
9683         p_type = PTR_TYPE(SPEC_OCLS(etype));
9684
9685 /*      if (SPEC_OCLS(etype)->codesp ) { */
9686 /*          p_type = CPOINTER ;  */
9687 /*      } */
9688 /*      else */
9689 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9690 /*              p_type = FPOINTER ; */
9691 /*          else */
9692 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9693 /*                  p_type = PPOINTER ; */
9694 /*              else */
9695 /*                  if (SPEC_OCLS(etype) == idata ) */
9696 /*                      p_type = IPOINTER ; */
9697 /*                  else */
9698 /*                      p_type = POINTER ; */
9699     }
9700
9701     /* now that we have the pointer type we assign
9702     the pointer values */
9703     switch (p_type) {
9704
9705     case POINTER:
9706     case IPOINTER:
9707         genNearPointerSet (right,result,ic);
9708         break;
9709
9710     case PPOINTER:
9711         genPagedPointerSet (right,result,ic);
9712         break;
9713
9714     case FPOINTER:
9715         genFarPointerSet (right,result,ic);
9716         break;
9717
9718     case GPOINTER:
9719         genGenPointerSet (right,result,ic);
9720         break;
9721
9722     default:
9723       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9724               "genPointerSet: illegal pointer type");
9725     }
9726 }
9727
9728 /*-----------------------------------------------------------------*/
9729 /* genIfx - generate code for Ifx statement                        */
9730 /*-----------------------------------------------------------------*/
9731 static void genIfx (iCode *ic, iCode *popIc)
9732 {
9733   operand *cond = IC_COND(ic);
9734   int isbit =0;
9735
9736   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9737
9738   pic16_aopOp(cond,ic,FALSE);
9739
9740   /* get the value into acc */
9741   if (AOP_TYPE(cond) != AOP_CRY)
9742     pic16_toBoolean(cond);
9743   else
9744     isbit = 1;
9745   /* the result is now in the accumulator */
9746   pic16_freeAsmop(cond,NULL,ic,TRUE);
9747
9748   /* if there was something to be popped then do it */
9749   if (popIc)
9750     genIpop(popIc);
9751
9752   /* if the condition is  a bit variable */
9753   if (isbit && IS_ITEMP(cond) && 
9754       SPIL_LOC(cond)) {
9755     genIfxJump(ic,SPIL_LOC(cond)->rname);
9756     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9757   }
9758   else {
9759     if (isbit && !IS_ITEMP(cond))
9760       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9761     else
9762       genIfxJump(ic,"a");
9763   }
9764   ic->generated = 1;
9765
9766 }
9767
9768 /*-----------------------------------------------------------------*/
9769 /* genAddrOf - generates code for address of                       */
9770 /*-----------------------------------------------------------------*/
9771 static void genAddrOf (iCode *ic)
9772 {
9773   operand *result, *left;
9774   int size;
9775   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9776   pCodeOp *pcop0, *pcop1, *pcop2;
9777
9778         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9779
9780         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9781         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9782
9783         sym = OP_SYMBOL( left );
9784
9785         size = AOP_SIZE(IC_RESULT(ic));
9786
9787         if(pic16_debug_verbose) {
9788                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9789                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9790         }
9791         
9792         /* Assume that what we want the address of is in data space
9793          * since there is no stack on the PIC, yet! -- VR */
9794         /* low */
9795         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9796
9797         /* high */
9798         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9799         
9800         /* upper */
9801         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9802         
9803
9804         if (size == 3) {
9805                 pic16_emitpcode(POC_MOVLW, pcop0);
9806                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9807                 pic16_emitpcode(POC_MOVLW, pcop1);
9808                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9809                 pic16_emitpcode(POC_MOVLW, pcop2);
9810                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9811         } else
9812         if (size == 2) {
9813                 pic16_emitpcode(POC_MOVLW, pcop0);
9814                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9815                 pic16_emitpcode(POC_MOVLW, pcop1);
9816                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9817         } else {
9818                 pic16_emitpcode(POC_MOVLW, pcop0);
9819                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9820         }
9821
9822         pic16_freeAsmop(result,NULL,ic,TRUE);
9823         pic16_freeAsmop(left, NULL, ic, FALSE);
9824 }
9825
9826
9827 #if 0
9828 /*-----------------------------------------------------------------*/
9829 /* genFarFarAssign - assignment when both are in far space         */
9830 /*-----------------------------------------------------------------*/
9831 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9832 {
9833     int size = AOP_SIZE(right);
9834     int offset = 0;
9835     char *l ;
9836     /* first push the right side on to the stack */
9837     while (size--) {
9838         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9839         MOVA(l);
9840         pic16_emitcode ("push","acc");
9841     }
9842     
9843     pic16_freeAsmop(right,NULL,ic,FALSE);
9844     /* now assign DPTR to result */
9845     pic16_aopOp(result,ic,FALSE);
9846     size = AOP_SIZE(result);
9847     while (size--) {
9848         pic16_emitcode ("pop","acc");
9849         pic16_aopPut(AOP(result),"a",--offset);
9850     }
9851     pic16_freeAsmop(result,NULL,ic,FALSE);
9852         
9853 }
9854 #endif
9855
9856 /*-----------------------------------------------------------------*/
9857 /* genAssign - generate code for assignment                        */
9858 /*-----------------------------------------------------------------*/
9859 static void genAssign (iCode *ic)
9860 {
9861   operand *result, *right;
9862   int size, offset,know_W;
9863   unsigned long lit = 0L;
9864
9865   result = IC_RESULT(ic);
9866   right  = IC_RIGHT(ic) ;
9867
9868   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9869   
9870   /* if they are the same */
9871   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9872     return ;
9873
9874   pic16_aopOp(right,ic,FALSE);
9875   pic16_aopOp(result,ic,TRUE);
9876
9877   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9878
9879   /* if they are the same registers */
9880   if (pic16_sameRegs(AOP(right),AOP(result)))
9881     goto release;
9882
9883   /* if the result is a bit */
9884   if (AOP_TYPE(result) == AOP_CRY) {
9885     /* if the right size is a literal then
9886        we know what the value is */
9887     if (AOP_TYPE(right) == AOP_LIT) {
9888           
9889       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9890                   pic16_popGet(AOP(result),0));
9891
9892       if (((int) operandLitValue(right))) 
9893         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9894                        AOP(result)->aopu.aop_dir,
9895                        AOP(result)->aopu.aop_dir);
9896       else
9897         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9898                        AOP(result)->aopu.aop_dir,
9899                        AOP(result)->aopu.aop_dir);
9900       goto release;
9901     }
9902
9903     /* the right is also a bit variable */
9904     if (AOP_TYPE(right) == AOP_CRY) {
9905       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9906       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9907       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9908
9909       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9910                      AOP(result)->aopu.aop_dir,
9911                      AOP(result)->aopu.aop_dir);
9912       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9913                      AOP(right)->aopu.aop_dir,
9914                      AOP(right)->aopu.aop_dir);
9915       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9916                      AOP(result)->aopu.aop_dir,
9917                      AOP(result)->aopu.aop_dir);
9918       goto release ;
9919     }
9920
9921     /* we need to or */
9922     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9923     pic16_toBoolean(right);
9924     emitSKPZ;
9925     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9926     //pic16_aopPut(AOP(result),"a",0);
9927     goto release ;
9928   }
9929
9930   /* bit variables done */
9931   /* general case */
9932   size = AOP_SIZE(result);
9933   offset = 0 ;
9934   if(AOP_TYPE(right) == AOP_LIT)
9935     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9936
9937 /* VR - What is this?! */
9938   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9939   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9940     if(aopIdx(AOP(result),0) == 4) {
9941   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9942       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9943       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9944       goto release;
9945     } else
9946       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9947   }
9948
9949   know_W=-1;
9950   while (size--) {
9951   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9952     if(AOP_TYPE(right) == AOP_LIT) {
9953       if(lit&0xff) {
9954         if(know_W != (lit&0xff))
9955           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9956         know_W = lit&0xff;
9957         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9958       } else
9959         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9960
9961       lit >>= 8;
9962
9963     } else if (AOP_TYPE(right) == AOP_CRY) {
9964       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9965       if(offset == 0) {
9966         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9967         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9968       }
9969     } else {
9970   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9971
9972 #if 1
9973         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9974            normally should work, but mind that the W register live range
9975            is not checked, so if the code generator assumes that the W
9976            is already loaded after such a pair, wrong code will be generated.
9977            
9978            Checking the live range is the next step.
9979            This is experimental code yet and has not been fully tested yet.
9980            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9981            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9982            
9983         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9984 #else   
9985         /* This is the old code, which is assumed(?!) that works fine(!?) */
9986
9987         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9988         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9989 #endif
9990     }
9991             
9992     offset++;
9993   }
9994
9995     
9996  release:
9997   pic16_freeAsmop (right,NULL,ic,FALSE);
9998   pic16_freeAsmop (result,NULL,ic,TRUE);
9999 }   
10000
10001 /*-----------------------------------------------------------------*/
10002 /* genJumpTab - generates code for jump table                       */
10003 /*-----------------------------------------------------------------*/
10004 static void genJumpTab (iCode *ic)
10005 {
10006     symbol *jtab;
10007     char *l;
10008
10009     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10010
10011     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10012     /* get the condition into accumulator */
10013     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10014     MOVA(l);
10015     /* multiply by three */
10016     pic16_emitcode("add","a,acc");
10017     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10018
10019     jtab = newiTempLabel(NULL);
10020     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10021     pic16_emitcode("jmp","@a+dptr");
10022     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10023
10024     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10025     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10026     emitSKPNC;
10027     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10028     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10029     pic16_emitpLabel(jtab->key);
10030
10031     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10032
10033     /* now generate the jump labels */
10034     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10035          jtab = setNextItem(IC_JTLABELS(ic))) {
10036         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10037         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10038         
10039     }
10040
10041 }
10042
10043 /*-----------------------------------------------------------------*/
10044 /* genMixedOperation - gen code for operators between mixed types  */
10045 /*-----------------------------------------------------------------*/
10046 /*
10047   TSD - Written for the PIC port - but this unfortunately is buggy.
10048   This routine is good in that it is able to efficiently promote 
10049   types to different (larger) sizes. Unfortunately, the temporary
10050   variables that are optimized out by this routine are sometimes
10051   used in other places. So until I know how to really parse the 
10052   iCode tree, I'm going to not be using this routine :(.
10053 */
10054 static int genMixedOperation (iCode *ic)
10055 {
10056 #if 0
10057   operand *result = IC_RESULT(ic);
10058   sym_link *ctype = operandType(IC_LEFT(ic));
10059   operand *right = IC_RIGHT(ic);
10060   int ret = 0;
10061   int big,small;
10062   int offset;
10063
10064   iCode *nextic;
10065   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10066
10067   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10068
10069   nextic = ic->next;
10070   if(!nextic)
10071     return 0;
10072
10073   nextright = IC_RIGHT(nextic);
10074   nextleft  = IC_LEFT(nextic);
10075   nextresult = IC_RESULT(nextic);
10076
10077   pic16_aopOp(right,ic,FALSE);
10078   pic16_aopOp(result,ic,FALSE);
10079   pic16_aopOp(nextright,  nextic, FALSE);
10080   pic16_aopOp(nextleft,   nextic, FALSE);
10081   pic16_aopOp(nextresult, nextic, FALSE);
10082
10083   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10084
10085     operand *t = right;
10086     right = nextright;
10087     nextright = t; 
10088
10089     pic16_emitcode(";remove right +","");
10090
10091   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10092 /*
10093     operand *t = right;
10094     right = nextleft;
10095     nextleft = t; 
10096 */
10097     pic16_emitcode(";remove left +","");
10098   } else
10099     return 0;
10100
10101   big = AOP_SIZE(nextleft);
10102   small = AOP_SIZE(nextright);
10103
10104   switch(nextic->op) {
10105
10106   case '+':
10107     pic16_emitcode(";optimize a +","");
10108     /* if unsigned or not an integral type */
10109     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10110       pic16_emitcode(";add a bit to something","");
10111     } else {
10112
10113       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10114
10115       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10116         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10117         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10118       } else
10119         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10120
10121       offset = 0;
10122       while(--big) {
10123
10124         offset++;
10125
10126         if(--small) {
10127           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10128             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10129             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10130           }
10131
10132           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10133           emitSKPNC;
10134           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10135                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10136                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10137           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10138           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10139
10140         } else {
10141           pic16_emitcode("rlf","known_zero,w");
10142
10143           /*
10144             if right is signed
10145               btfsc  right,7
10146                addlw ff
10147           */
10148           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10149             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10150             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10151           } else {
10152             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10153           }
10154         }
10155       }
10156       ret = 1;
10157     }
10158   }
10159   ret = 1;
10160
10161 release:
10162   pic16_freeAsmop(right,NULL,ic,TRUE);
10163   pic16_freeAsmop(result,NULL,ic,TRUE);
10164   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10165   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10166   if(ret)
10167     nextic->generated = 1;
10168
10169   return ret;
10170 #else
10171   return 0;
10172 #endif
10173 }
10174 /*-----------------------------------------------------------------*/
10175 /* genCast - gen code for casting                                  */
10176 /*-----------------------------------------------------------------*/
10177 static void genCast (iCode *ic)
10178 {
10179   operand *result = IC_RESULT(ic);
10180   sym_link *ctype = operandType(IC_LEFT(ic));
10181   sym_link *rtype = operandType(IC_RIGHT(ic));
10182   operand *right = IC_RIGHT(ic);
10183   int size, offset ;
10184
10185         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10186         /* if they are equivalent then do nothing */
10187         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10188                 return ;
10189
10190         pic16_aopOp(right,ic,FALSE) ;
10191         pic16_aopOp(result,ic,FALSE);
10192
10193         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10194
10195         /* if the result is a bit */
10196         if (AOP_TYPE(result) == AOP_CRY) {
10197         
10198                 /* if the right size is a literal then
10199                  * we know what the value is */
10200                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10201
10202                 if (AOP_TYPE(right) == AOP_LIT) {
10203                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10204                                 pic16_popGet(AOP(result),0));
10205
10206                         if (((int) operandLitValue(right))) 
10207                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10208                                         AOP(result)->aopu.aop_dir,
10209                                         AOP(result)->aopu.aop_dir);
10210                         else
10211                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10212                                         AOP(result)->aopu.aop_dir,
10213                                         AOP(result)->aopu.aop_dir);
10214                         goto release;
10215                 }
10216
10217                 /* the right is also a bit variable */
10218                 if (AOP_TYPE(right) == AOP_CRY) {
10219                         emitCLRC;
10220                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10221
10222                         pic16_emitcode("clrc","");
10223                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10224                                 AOP(right)->aopu.aop_dir,
10225                                 AOP(right)->aopu.aop_dir);
10226                         pic16_aopPut(AOP(result),"c",0);
10227                         goto release ;
10228                 }
10229
10230                 /* we need to or */
10231                 if (AOP_TYPE(right) == AOP_REG) {
10232                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10233                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10234                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10235                 }
10236                 pic16_toBoolean(right);
10237                 pic16_aopPut(AOP(result),"a",0);
10238                 goto release ;
10239         }
10240
10241         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10242           int offset = 1;
10243
10244                 size = AOP_SIZE(result);
10245
10246                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10247
10248                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10249                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10250                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10251
10252                 while (size--)
10253                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10254
10255                 goto release;
10256         }
10257
10258         /* if they are the same size : or less */
10259         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10260
10261                 /* if they are in the same place */
10262                 if (pic16_sameRegs(AOP(right),AOP(result)))
10263                         goto release;
10264
10265                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10266 #if 0
10267                 if (IS_PTR_CONST(rtype))
10268 #else
10269                 if (IS_CODEPTR(rtype))
10270 #endif
10271                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10272
10273 #if 0
10274                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10275 #else
10276                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10277 #endif
10278                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10279
10280 #if 0
10281                 if(AOP_TYPE(right) == AOP_IMMD) {
10282                   pCodeOp *pcop0, *pcop1, *pcop2;
10283                   symbol *sym = OP_SYMBOL( right );
10284
10285                         size = AOP_SIZE(result);
10286                         /* low */
10287                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10288                         /* high */
10289                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10290                         /* upper */
10291                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10292         
10293                         if (size == 3) {
10294                                 pic16_emitpcode(POC_MOVLW, pcop0);
10295                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10296                                 pic16_emitpcode(POC_MOVLW, pcop1);
10297                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10298                                 pic16_emitpcode(POC_MOVLW, pcop2);
10299                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10300                         } else
10301                         if (size == 2) {
10302                                 pic16_emitpcode(POC_MOVLW, pcop0);
10303                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10304                                 pic16_emitpcode(POC_MOVLW, pcop1);
10305                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10306                         } else {
10307                                 pic16_emitpcode(POC_MOVLW, pcop0);
10308                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10309                         }
10310                 } else
10311 #endif
10312                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10313                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10314                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10315                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10316                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10317                         if(AOP_SIZE(result) <2)
10318                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10319                 } else {
10320                         /* if they in different places then copy */
10321                         size = AOP_SIZE(result);
10322                         offset = 0 ;
10323                         while (size--) {
10324                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10325                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10326                                 offset++;
10327                         }
10328                 }
10329                 goto release;
10330         }
10331
10332         /* if the result is of type pointer */
10333         if (IS_PTR(ctype)) {
10334           int p_type;
10335           sym_link *type = operandType(right);
10336           sym_link *etype = getSpec(type);
10337
10338                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10339
10340                 /* pointer to generic pointer */
10341                 if (IS_GENPTR(ctype)) {
10342                   char *l = zero;
10343             
10344                         if (IS_PTR(type)) 
10345                                 p_type = DCL_TYPE(type);
10346                         else {
10347                 /* we have to go by the storage class */
10348                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10349
10350 /*              if (SPEC_OCLS(etype)->codesp )  */
10351 /*                  p_type = CPOINTER ;  */
10352 /*              else */
10353 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10354 /*                      p_type = FPOINTER ; */
10355 /*                  else */
10356 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10357 /*                          p_type = PPOINTER; */
10358 /*                      else */
10359 /*                          if (SPEC_OCLS(etype) == idata ) */
10360 /*                              p_type = IPOINTER ; */
10361 /*                          else */
10362 /*                              p_type = POINTER ; */
10363             }
10364                 
10365             /* the first two bytes are known */
10366       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10367             size = GPTRSIZE - 1; 
10368             offset = 0 ;
10369             while (size--) {
10370               if(offset < AOP_SIZE(right)) {
10371       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10372                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10373                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10374                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10375                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10376                 } else { 
10377                   pic16_aopPut(AOP(result),
10378                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10379                          offset);
10380                 }
10381               } else 
10382                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10383               offset++;
10384             }
10385             /* the last byte depending on type */
10386             switch (p_type) {
10387             case IPOINTER:
10388             case POINTER:
10389                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10390                 break;
10391             case FPOINTER:
10392               pic16_emitcode(";BUG!? ","%d",__LINE__);
10393                 l = one;
10394                 break;
10395             case CPOINTER:
10396               pic16_emitcode(";BUG!? ","%d",__LINE__);
10397                 l = "#0x02";
10398                 break;                          
10399             case PPOINTER:
10400               pic16_emitcode(";BUG!? ","%d",__LINE__);
10401                 l = "#0x03";
10402                 break;
10403                 
10404             default:
10405                 /* this should never happen */
10406                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10407                        "got unknown pointer type");
10408                 exit(1);
10409             }
10410             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10411             goto release ;
10412         }
10413         
10414         /* just copy the pointers */
10415         size = AOP_SIZE(result);
10416         offset = 0 ;
10417         while (size--) {
10418             pic16_aopPut(AOP(result),
10419                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10420                    offset);
10421             offset++;
10422         }
10423         goto release ;
10424     }
10425     
10426
10427
10428     /* so we now know that the size of destination is greater
10429     than the size of the source.
10430     Now, if the next iCode is an operator then we might be
10431     able to optimize the operation without performing a cast.
10432     */
10433     if(genMixedOperation(ic))
10434       goto release;
10435
10436     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10437     
10438     /* we move to result for the size of source */
10439     size = AOP_SIZE(right);
10440     offset = 0 ;
10441     while (size--) {
10442       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10443       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10444       offset++;
10445     }
10446
10447     /* now depending on the sign of the destination */
10448     size = AOP_SIZE(result) - AOP_SIZE(right);
10449     /* if unsigned or not an integral type */
10450     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10451       while (size--)
10452         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10453     } else {
10454       /* we need to extend the sign :( */
10455
10456       if(size == 1) {
10457         /* Save one instruction of casting char to int */
10458         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10459         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10460         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10461       } else {
10462         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10463
10464         if(offset)
10465           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10466         else
10467           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10468         
10469         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10470
10471         while (size--)
10472           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10473       }
10474     }
10475
10476 release:
10477     pic16_freeAsmop(right,NULL,ic,TRUE);
10478     pic16_freeAsmop(result,NULL,ic,TRUE);
10479
10480 }
10481
10482 /*-----------------------------------------------------------------*/
10483 /* genDjnz - generate decrement & jump if not zero instrucion      */
10484 /*-----------------------------------------------------------------*/
10485 static int genDjnz (iCode *ic, iCode *ifx)
10486 {
10487     symbol *lbl, *lbl1;
10488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10489
10490     if (!ifx)
10491         return 0;
10492     
10493     /* if the if condition has a false label
10494        then we cannot save */
10495     if (IC_FALSE(ifx))
10496         return 0;
10497
10498     /* if the minus is not of the form 
10499        a = a - 1 */
10500     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10501         !IS_OP_LITERAL(IC_RIGHT(ic)))
10502         return 0;
10503
10504     if (operandLitValue(IC_RIGHT(ic)) != 1)
10505         return 0;
10506
10507     /* if the size of this greater than one then no
10508        saving */
10509     if (getSize(operandType(IC_RESULT(ic))) > 1)
10510         return 0;
10511
10512     /* otherwise we can save BIG */
10513     lbl = newiTempLabel(NULL);
10514     lbl1= newiTempLabel(NULL);
10515
10516     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10517     
10518     if (IS_AOP_PREG(IC_RESULT(ic))) {
10519         pic16_emitcode("dec","%s",
10520                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10521         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10522         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10523     } else {    
10524
10525
10526       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10527       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10528
10529       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10530       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10531
10532     }
10533 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10534 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10535 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10536 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10537
10538     
10539     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10540     ifx->generated = 1;
10541     return 1;
10542 }
10543
10544 /*-----------------------------------------------------------------*/
10545 /* genReceive - generate code for a receive iCode                  */
10546 /*-----------------------------------------------------------------*/
10547 static void genReceive (iCode *ic)
10548 {    
10549         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10550
10551         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10552                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10553                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10554
10555           int size = getSize(operandType(IC_RESULT(ic)));
10556           int offset =  pic16_fReturnSizePic - size;
10557
10558                 while (size--) {
10559                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10560                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10561                         offset++;
10562                 }
10563
10564                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10565
10566                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10567                 size = AOP_SIZE(IC_RESULT(ic));
10568                 offset = 0;
10569                 while (size--) {
10570                         pic16_emitcode ("pop","acc");
10571                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10572                 }
10573         } else {
10574                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10575
10576                 _G.accInUse++;
10577                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10578                 _G.accInUse--;
10579                 assignResultValue(IC_RESULT(ic), 0);
10580         }
10581
10582         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10583 }
10584
10585 /*-----------------------------------------------------------------*/
10586 /* genDummyRead - generate code for dummy read of volatiles        */
10587 /*-----------------------------------------------------------------*/
10588 static void
10589 genDummyRead (iCode * ic)
10590 {
10591   pic16_emitcode ("; genDummyRead","");
10592   pic16_emitcode ("; not implemented","");
10593
10594   ic = ic;
10595 }
10596
10597 /*-----------------------------------------------------------------*/
10598 /* genpic16Code - generate code for pic16 based controllers        */
10599 /*-----------------------------------------------------------------*/
10600 /*
10601  * At this point, ralloc.c has gone through the iCode and attempted
10602  * to optimize in a way suitable for a PIC. Now we've got to generate
10603  * PIC instructions that correspond to the iCode.
10604  *
10605  * Once the instructions are generated, we'll pass through both the
10606  * peep hole optimizer and the pCode optimizer.
10607  *-----------------------------------------------------------------*/
10608
10609 void genpic16Code (iCode *lic)
10610 {
10611     iCode *ic;
10612     int cln = 0;
10613
10614     lineHead = lineCurr = NULL;
10615
10616     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10617     pic16_addpBlock(pb);
10618
10619 #if 0
10620     /* if debug information required */
10621     if (options.debug && currFunc) {
10622       if (currFunc) {
10623         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10624         _G.debugLine = 1;
10625         if (IS_STATIC(currFunc->etype)) {
10626           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10627           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10628         } else {
10629           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10630           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10631         }
10632         _G.debugLine = 0;
10633       }
10634     }
10635 #endif
10636
10637     for (ic = lic ; ic ; ic = ic->next ) {
10638
10639       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10640         if ( cln != ic->lineno ) {
10641             if ( options.debug ) {
10642                 _G.debugLine = 1;
10643                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10644                          FileBaseName(ic->filename),ic->lineno,
10645                          ic->level,ic->block);
10646                 _G.debugLine = 0;
10647             }
10648             
10649             if(!options.noCcodeInAsm) {
10650                 pic16_addpCode2pBlock(pb,
10651                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10652                                 printCLine(ic->filename, ic->lineno)));
10653             }
10654
10655             cln = ic->lineno ;
10656         }
10657         
10658         if(options.iCodeInAsm) {
10659                 /* insert here code to print iCode as comment */
10660                 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
10661         }
10662         
10663         /* if the result is marked as
10664            spilt and rematerializable or code for
10665            this has already been generated then
10666            do nothing */
10667         if (resultRemat(ic) || ic->generated ) 
10668             continue ;
10669         
10670         /* depending on the operation */
10671         switch (ic->op) {
10672         case '!' :
10673             pic16_genNot(ic);
10674             break;
10675             
10676         case '~' :
10677             pic16_genCpl(ic);
10678             break;
10679             
10680         case UNARYMINUS:
10681             genUminus (ic);
10682             break;
10683             
10684         case IPUSH:
10685             genIpush (ic);
10686             break;
10687             
10688         case IPOP:
10689             /* IPOP happens only when trying to restore a 
10690                spilt live range, if there is an ifx statement
10691                following this pop then the if statement might
10692                be using some of the registers being popped which
10693                would destroy the contents of the register so
10694                we need to check for this condition and handle it */
10695             if (ic->next            && 
10696                 ic->next->op == IFX &&
10697                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10698                 genIfx (ic->next,ic);
10699             else
10700                 genIpop (ic);
10701             break; 
10702             
10703         case CALL:
10704             genCall (ic);
10705             break;
10706             
10707         case PCALL:
10708             genPcall (ic);
10709             break;
10710             
10711         case FUNCTION:
10712             genFunction (ic);
10713             break;
10714             
10715         case ENDFUNCTION:
10716             genEndFunction (ic);
10717             break;
10718             
10719         case RETURN:
10720             genRet (ic);
10721             break;
10722             
10723         case LABEL:
10724             genLabel (ic);
10725             break;
10726             
10727         case GOTO:
10728             genGoto (ic);
10729             break;
10730             
10731         case '+' :
10732             pic16_genPlus (ic) ;
10733             break;
10734             
10735         case '-' :
10736             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10737                 pic16_genMinus (ic);
10738             break;
10739             
10740         case '*' :
10741             genMult (ic);
10742             break;
10743             
10744         case '/' :
10745             genDiv (ic) ;
10746             break;
10747             
10748         case '%' :
10749             genMod (ic);
10750             break;
10751             
10752         case '>' :
10753             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10754             break;
10755             
10756         case '<' :
10757             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10758             break;
10759             
10760         case LE_OP:
10761         case GE_OP:
10762         case NE_OP:
10763             
10764             /* note these two are xlated by algebraic equivalence
10765                during parsing SDCC.y */
10766             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10767                    "got '>=' or '<=' shouldn't have come here");
10768             break;      
10769             
10770         case EQ_OP:
10771             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10772             break;          
10773             
10774         case AND_OP:
10775             genAndOp (ic);
10776             break;
10777             
10778         case OR_OP:
10779             genOrOp (ic);
10780             break;
10781             
10782         case '^' :
10783             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10784             break;
10785             
10786         case '|' :
10787                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10788             break;
10789             
10790         case BITWISEAND:
10791             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10792             break;
10793             
10794         case INLINEASM:
10795             genInline (ic);
10796             break;
10797             
10798         case RRC:
10799             genRRC (ic);
10800             break;
10801             
10802         case RLC:
10803             genRLC (ic);
10804             break;
10805             
10806         case GETHBIT:
10807             genGetHbit (ic);
10808             break;
10809             
10810         case LEFT_OP:
10811             genLeftShift (ic);
10812             break;
10813             
10814         case RIGHT_OP:
10815             genRightShift (ic);
10816             break;
10817             
10818         case GET_VALUE_AT_ADDRESS:
10819             genPointerGet(ic);
10820             break;
10821             
10822         case '=' :
10823             if (POINTER_SET(ic))
10824                 genPointerSet(ic);
10825             else
10826                 genAssign(ic);
10827             break;
10828             
10829         case IFX:
10830             genIfx (ic,NULL);
10831             break;
10832             
10833         case ADDRESS_OF:
10834             genAddrOf (ic);
10835             break;
10836             
10837         case JUMPTABLE:
10838             genJumpTab (ic);
10839             break;
10840             
10841         case CAST:
10842             genCast (ic);
10843             break;
10844             
10845         case RECEIVE:
10846             genReceive(ic);
10847             break;
10848             
10849         case SEND:
10850             addSet(&_G.sendSet,ic);
10851             break;
10852
10853         case DUMMY_READ_VOLATILE:
10854           genDummyRead (ic);
10855           break;
10856
10857         default :
10858             ic = ic;
10859         }
10860     }
10861
10862
10863     /* now we are ready to call the
10864        peep hole optimizer */
10865     if (!options.nopeep) {
10866       peepHole (&lineHead);
10867     }
10868     /* now do the actual printing */
10869     printLine (lineHead,codeOutFile);
10870
10871 #ifdef PCODE_DEBUG
10872     DFPRINTF((stderr,"printing pBlock\n\n"));
10873     pic16_printpBlock(stdout,pb);
10874 #endif
10875
10876     return;
10877 }
10878