]
[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 void pic16_genMult16X16_16(operand *, operand *, operand *);
53 void pic16_genMult32X32_32(operand *, operand *, operand *);
54 pCode *pic16_AssembleLine(char *line, int peeps);
55 extern void pic16_printpBlock(FILE *of, pBlock *pb);
56 static asmop *newAsmop (short type);
57 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
58 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
59 static void mov2w (asmop *aop, int offset);
60 static int aopIdx (asmop *aop, int offset);
61
62 static int labelOffset=0;
63 extern int pic16_debug_verbose;
64 static int optimized_for_speed = 0;
65 /*
66   hack hack
67
68 */
69
70 /* max_key keeps track of the largest label number used in 
71    a function. This is then used to adjust the label offset
72    for the next function.
73 */
74 static int max_key=0;
75 static int GpsuedoStkPtr=0;
76
77 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
78 unsigned int pic16aopLiteral (value *val, int offset);
79 const char *pic16_AopType(short type);
80 static iCode *ifxForOp ( operand *op, iCode *ic );
81
82 void pic16_pushpCodeOp(pCodeOp *pcop);
83 void pic16_poppCodeOp(pCodeOp *pcop);
84
85
86
87 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
88
89 /* this is the down and dirty file with all kinds of 
90    kludgy & hacky stuff. This is what it is all about
91    CODE GENERATION for a specific MCU . some of the
92    routines may be reusable, will have to see */
93
94 static char *zero = "#0x00";
95 static char *one  = "#0x01";
96 static char *spname = "sp";
97
98
99 /*
100  * Function return value policy (MSB-->LSB):
101  *  8 bits      -> WREG
102  * 16 bits      -> PRODL:WREG
103  * 24 bits      -> PRODH:PRODL:WREG
104  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
105  * >32 bits     -> on stack, and FSR0 points to the beginning
106  *
107  */
108  
109
110 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
111 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
112 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
113 static char **fReturn = fReturnpic16;
114
115 static char *accUse[] = {"WREG"};
116
117 //static short rbank = -1;
118
119 static struct {
120     short r0Pushed;
121     short r1Pushed;
122     short accInUse;
123     short inLine;
124     short debugLine;
125     short nRegsSaved;
126     set *sendSet;
127     int interruptvector;
128 } _G;
129
130 /* Resolved ifx structure. This structure stores information
131    about an iCode ifx that makes it easier to generate code.
132 */
133 typedef struct resolvedIfx {
134   symbol *lbl;     /* pointer to a label */
135   int condition;   /* true or false ifx */
136   int generated;   /* set true when the code associated with the ifx
137                     * is generated */
138 } resolvedIfx;
139
140 extern int pic16_ptrRegReq ;
141 extern int pic16_nRegs;
142 extern FILE *codeOutFile;
143 static void saverbank (int, iCode *,bool);
144
145 static lineNode *lineHead = NULL;
146 static lineNode *lineCurr = NULL;
147
148 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
149 0xE0, 0xC0, 0x80, 0x00};
150 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
151 0x07, 0x03, 0x01, 0x00};
152
153 static  pBlock *pb;
154
155 /*-----------------------------------------------------------------*/
156 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
157 /*                 exponent of 2 is returned, otherwise -1 is      */
158 /*                 returned.                                       */
159 /* note that this is similar to the function `powof2' in SDCCsymt  */
160 /* if(n == 2^y)                                                    */
161 /*   return y;                                                     */
162 /* return -1;                                                      */
163 /*-----------------------------------------------------------------*/
164 static int my_powof2 (unsigned long num)
165 {
166   if(num) {
167     if( (num & (num-1)) == 0) {
168       int nshifts = -1;
169       while(num) {
170         num>>=1;
171         nshifts++;
172       }
173       return nshifts;
174     }
175   }
176
177   return -1;
178 }
179
180 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
181 {
182   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
183                        line_no,
184                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
185                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
186                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
187                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
188                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
189                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
190                        ((result) ? AOP_SIZE(result) : 0));
191 }
192
193 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
194 {
195
196   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
197                        line_no,
198                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
199                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
200                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
201                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
202                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
203                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
204
205 }
206
207 void pic16_emitpcomment (char *fmt, ...)
208 {
209     va_list ap;
210     char lb[INITIAL_INLINEASM];  
211     char *lbp = lb;
212
213     va_start(ap,fmt);   
214
215     lb[0] = ';';
216     vsprintf(lb+1,fmt,ap);
217
218     while (isspace(*lbp)) lbp++;
219
220     if (lbp && *lbp) 
221         lineCurr = (lineCurr ?
222                     connectLine(lineCurr,newLineNode(lb)) :
223                     (lineHead = newLineNode(lb)));
224     lineCurr->isInline = _G.inLine;
225     lineCurr->isDebug  = _G.debugLine;
226
227     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
228     va_end(ap);
229
230 //      fprintf(stderr, "%s\n", lb);
231 }
232
233 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     if(!pic16_debug_verbose)
240       return;
241
242     va_start(ap,fmt);   
243
244     if (inst && *inst) {
245         if (fmt && *fmt)
246             sprintf(lb,"%s\t",inst);
247         else
248             sprintf(lb,"%s",inst);
249         vsprintf(lb+(strlen(lb)),fmt,ap);
250     }  else
251         vsprintf(lb,fmt,ap);
252
253     while (isspace(*lbp)) lbp++;
254
255     if (lbp && *lbp) 
256         lineCurr = (lineCurr ?
257                     connectLine(lineCurr,newLineNode(lb)) :
258                     (lineHead = newLineNode(lb)));
259     lineCurr->isInline = _G.inLine;
260     lineCurr->isDebug  = _G.debugLine;
261
262     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
263     va_end(ap);
264
265 //      fprintf(stderr, "%s\n", lb);
266 }
267
268 void pic16_emitpLabel(int key)
269 {
270   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
271 }
272
273 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
274 {
275
276   if(pcop)
277     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
278   else
279     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
280     
281 //    fprintf(stderr, "%s\n", pcop->name);
282 }
283
284 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
285 {
286
287   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
288
289 }
290
291
292 #if 1
293 #define pic16_emitcode  DEBUGpic16_emitcode
294 #else
295 /*-----------------------------------------------------------------*/
296 /* pic16_emitcode - writes the code into a file : for now it is simple    */
297 /*-----------------------------------------------------------------*/
298 void pic16_emitcode (char *inst,char *fmt, ...)
299 {
300     va_list ap;
301     char lb[INITIAL_INLINEASM];  
302     char *lbp = lb;
303
304     va_start(ap,fmt);   
305
306     if (inst && *inst) {
307         if (fmt && *fmt)
308             sprintf(lb,"%s\t",inst);
309         else
310             sprintf(lb,"%s",inst);
311         vsprintf(lb+(strlen(lb)),fmt,ap);
312     }  else
313         vsprintf(lb,fmt,ap);
314
315     while (isspace(*lbp)) lbp++;
316
317     if (lbp && *lbp) 
318         lineCurr = (lineCurr ?
319                     connectLine(lineCurr,newLineNode(lb)) :
320                     (lineHead = newLineNode(lb)));
321     lineCurr->isInline = _G.inLine;
322     lineCurr->isDebug  = _G.debugLine;
323
324 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
325
326 //    if(pic16_debug_verbose)
327 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
328
329     va_end(ap);
330 }
331 #endif
332
333
334 /*-----------------------------------------------------------------*/
335 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
336 /*-----------------------------------------------------------------*/
337 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
338 {
339     bool r0iu = FALSE , r1iu = FALSE;
340     bool r0ou = FALSE , r1ou = FALSE;
341
342         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
343
344     /* the logic: if r0 & r1 used in the instruction
345     then we are in trouble otherwise */
346
347     /* first check if r0 & r1 are used by this
348     instruction, in which case we are in trouble */
349     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
350         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
351     {
352         goto endOfWorld;      
353     }
354
355     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
356     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
357
358     /* if no usage of r0 then return it */
359     if (!r0iu && !r0ou) {
360         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
361         (*aopp)->type = AOP_R0;
362         
363         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
364     }
365
366     /* if no usage of r1 then return it */
367     if (!r1iu && !r1ou) {
368         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
369         (*aopp)->type = AOP_R1;
370
371         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
372     }    
373
374     /* now we know they both have usage */
375     /* if r0 not used in this instruction */
376     if (!r0iu) {
377         /* push it if not already pushed */
378         if (!_G.r0Pushed) {
379           //pic16_emitcode ("push","%s",
380           //          pic16_regWithIdx(R0_IDX)->dname);
381             _G.r0Pushed++ ;
382         }
383         
384         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
385         (*aopp)->type = AOP_R0;
386
387         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
388     }
389
390     /* if r1 not used then */
391
392     if (!r1iu) {
393         /* push it if not already pushed */
394         if (!_G.r1Pushed) {
395           //pic16_emitcode ("push","%s",
396           //          pic16_regWithIdx(R1_IDX)->dname);
397             _G.r1Pushed++ ;
398         }
399         
400         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
401         (*aopp)->type = AOP_R1;
402         return pic16_regWithIdx(R1_IDX);
403     }
404
405 endOfWorld :
406     /* I said end of world but not quite end of world yet */
407     /* if this is a result then we can push it on the stack*/
408     if (result) {
409         (*aopp)->type = AOP_STK;    
410         return NULL;
411     }
412
413     /* other wise this is true end of the world */
414     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
415            "getFreePtr should never reach here");
416     exit(0);
417 }
418
419 /*-----------------------------------------------------------------*/
420 /* newAsmop - creates a new asmOp                                  */
421 /*-----------------------------------------------------------------*/
422 static asmop *newAsmop (short type)
423 {
424     asmop *aop;
425
426     aop = Safe_calloc(1,sizeof(asmop));
427     aop->type = type;
428     return aop;
429 }
430
431 static void genSetDPTR(int n)
432 {
433     if (!n)
434     {
435         pic16_emitcode(";", "Select standard DPTR");
436         pic16_emitcode("mov", "dps, #0x00");
437     }
438     else
439     {
440         pic16_emitcode(";", "Select alternate DPTR");
441         pic16_emitcode("mov", "dps, #0x01");
442     }
443 }
444
445 /*-----------------------------------------------------------------*/
446 /* resolveIfx - converts an iCode ifx into a form more useful for  */
447 /*              generating code                                    */
448 /*-----------------------------------------------------------------*/
449 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
450 {
451
452   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
453
454   if(!resIfx) 
455     return;
456
457
458   resIfx->condition = 1;    /* assume that the ifx is true */
459   resIfx->generated = 0;    /* indicate that the ifx has not been used */
460
461   if(!ifx) {
462     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
463
464 #if 1
465     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
466                         __FUNCTION__,__LINE__,resIfx->lbl->key);
467 #endif
468
469   } else {
470     if(IC_TRUE(ifx)) {
471       resIfx->lbl = IC_TRUE(ifx);
472     } else {
473       resIfx->lbl = IC_FALSE(ifx);
474       resIfx->condition = 0;
475     }
476 /*
477     if(IC_TRUE(ifx)) 
478       DEBUGpic16_emitcode("; ***","ifx true is non-null");
479     if(IC_FALSE(ifx)) 
480       DEBUGpic16_emitcode("; ***","ifx false is non-null");
481 */
482   }
483
484   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
485
486 }
487 #if 0
488 /*-----------------------------------------------------------------*/
489 /* pointerCode - returns the code for a pointer type               */
490 /*-----------------------------------------------------------------*/
491 static int pointerCode (sym_link *etype)
492 {
493
494     return PTR_TYPE(SPEC_OCLS(etype));
495
496 }
497 #endif
498 /*-----------------------------------------------------------------*/
499 /* aopForSym - for a true symbol                                   */
500 /*-----------------------------------------------------------------*/
501 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
502 {
503     asmop *aop;
504     memmap *space= SPEC_OCLS(sym->etype);
505
506     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
507     /* if already has one */
508     if (sym->aop) {
509             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
510         return sym->aop;
511     }
512
513     /* if symbol was initially placed onStack then we must re-place it
514      * to direct memory, since pic16 does not have a specific stack */
515     if(sym->onStack) {
516         sym->onStack = 0;
517         SPEC_OCLS( sym->etype ) = data;
518         space = data;
519     }
520     
521
522 #if 1
523     /* assign depending on the storage class */
524     /* if it is on the stack or indirectly addressable */
525     /* space we need to assign either r0 or r1 to it   */    
526     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
527
528         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
529                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
530         
531         sym->aop = aop = newAsmop(0);
532         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
533         aop->size = getSize(sym->type);
534
535         /* now assign the address of the variable to 
536         the pointer register */
537         if (aop->type != AOP_STK) {
538
539             if (sym->onStack) {
540                     if ( _G.accInUse )
541                         pic16_emitcode("push","acc");
542
543                     pic16_emitcode("mov","a,_bp");
544                     pic16_emitcode("add","a,#0x%02x",
545                              ((sym->stack < 0) ?
546                               ((char)(sym->stack - _G.nRegsSaved )) :
547                               ((char)sym->stack)) & 0xff);
548                     pic16_emitcode("mov","%s,a",
549                              aop->aopu.aop_ptr->name);
550
551                     if ( _G.accInUse )
552                         pic16_emitcode("pop","acc");
553             } else
554                 pic16_emitcode("mov","%s,#%s",
555                          aop->aopu.aop_ptr->name,
556                          sym->rname);
557             aop->paged = space->paged;
558         } else
559             aop->aopu.aop_stk = sym->stack;
560         return aop;
561     }
562 #endif
563
564     if (sym->onStack && options.stack10bit)
565     {
566         /* It's on the 10 bit stack, which is located in
567          * far data space.
568          */
569          
570       //DEBUGpic16_emitcode(";","%d",__LINE__);
571
572         if ( _G.accInUse )
573                 pic16_emitcode("push","acc");
574
575         pic16_emitcode("mov","a,_bp");
576         pic16_emitcode("add","a,#0x%02x",
577                  ((sym->stack < 0) ?
578                    ((char)(sym->stack - _G.nRegsSaved )) :
579                    ((char)sym->stack)) & 0xff);
580         
581         genSetDPTR(1);
582         pic16_emitcode ("mov","dpx1,#0x40");
583         pic16_emitcode ("mov","dph1,#0x00");
584         pic16_emitcode ("mov","dpl1, a");
585         genSetDPTR(0);
586         
587         if ( _G.accInUse )
588             pic16_emitcode("pop","acc");
589             
590         sym->aop = aop = newAsmop(AOP_DPTR2);
591         aop->size = getSize(sym->type); 
592         return aop;
593     }
594
595     //DEBUGpic16_emitcode(";","%d",__LINE__);
596     /* if in bit space */
597     if (IN_BITSPACE(space)) {
598         sym->aop = aop = newAsmop (AOP_CRY);
599         aop->aopu.aop_dir = sym->rname ;
600         aop->size = getSize(sym->type);
601         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
602         return aop;
603     }
604     /* if it is in direct space */
605     if (IN_DIRSPACE(space)) {
606         sym->aop = aop = newAsmop (AOP_DIR);
607         aop->aopu.aop_dir = sym->rname ;
608         aop->size = getSize(sym->type);
609         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
610         pic16_allocDirReg( IC_LEFT(ic) );
611         return aop;
612     }
613
614 #if 0                                                                                           // patch 14
615     /* special case for a function */
616     if (IS_FUNC(sym->type)) {   
617         sym->aop = aop = newAsmop(AOP_IMMD);    
618         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
619         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
620         strcpy(aop->aopu.aop_immd,sym->rname);
621         aop->size = FPTRSIZE; 
622         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
623         return aop;
624     }
625 #endif                                                                                          // patch 14
626
627
628     /* only remaining is far space */
629     /* in which case DPTR gets the address */
630     sym->aop = aop = newAsmop(AOP_PCODE);
631
632 /* change the next if to 1 to revert to good old immediate code */
633         if(IN_CODESPACE(space)) {
634                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
635                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
636                 PCOI(aop->aopu.pcop)->index = 0;
637         } else {
638                 /* try to allocate via direct register */
639                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
640 //              aop->size = getSize( sym->type );
641         }
642
643         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
644                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
645
646 #if 0
647         if(!pic16_allocDirReg (IC_LEFT(ic)))
648                 return NULL;
649 #endif
650
651         if(IN_DIRSPACE( space ))
652                 aop->size = PTRSIZE;
653         else if(IN_CODESPACE( space ))
654                 aop->size = FPTRSIZE;
655         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
656         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
657         else {
658                 assert( 0 );
659         }
660
661     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
662
663     /* if it is in code space */
664     if (IN_CODESPACE(space))
665         aop->code = 1;
666
667     return aop;     
668 }
669
670 /*-----------------------------------------------------------------*/
671 /* aopForRemat - rematerialzes an object                           */
672 /*-----------------------------------------------------------------*/
673 static asmop *aopForRemat (operand *op) // x symbol *sym)
674 {
675   symbol *sym = OP_SYMBOL(op);
676   iCode *ic = NULL, *oldic;
677   asmop *aop = newAsmop(AOP_PCODE);
678   int val = 0;
679   int offset = 0;
680   int viaimmd=0;
681
682
683         ic = sym->rematiCode;
684
685         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
686         
687         if(IS_OP_POINTER(op)) {
688                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
689         }
690
691         for (;;) {
692                 oldic = ic;
693
694 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
695         
696                 if (ic->op == '+') {
697                         val += (int) operandLitValue(IC_RIGHT(ic));
698                 } else if (ic->op == '-') {
699                         val -= (int) operandLitValue(IC_RIGHT(ic));
700                 } else
701                         break;
702                 
703                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
704         }
705
706         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
707
708         if(!op->isaddr)viaimmd++; else viaimmd=0;
709                 
710 /* set the following if to 1 to revert to good old immediate code */
711         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
712                 || viaimmd) {
713
714                 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
715
716                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
717
718 #if 0
719                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
720 #else
721                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
722 #endif
723
724                 PCOI(aop->aopu.pcop)->index = val;
725         } else {
726                 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
727
728                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
729 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
730         }
731
732
733         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
734                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
735 #if 0
736                 val, IS_PTR_CONST(operandType(op)));
737 #else
738                 val, IS_CODEPTR(operandType(op)));
739 #endif
740
741 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
742
743         pic16_allocDirReg (IC_LEFT(ic));
744
745         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
746                 aop->code = 1;
747
748   return aop;        
749 }
750
751 static int aopIdx (asmop *aop, int offset)
752 {
753   if(!aop)
754     return -1;
755
756   if(aop->type !=  AOP_REG)
757     return -2;
758         
759   return aop->aopu.aop_reg[offset]->rIdx;
760
761 }
762 /*-----------------------------------------------------------------*/
763 /* regsInCommon - two operands have some registers in common       */
764 /*-----------------------------------------------------------------*/
765 static bool regsInCommon (operand *op1, operand *op2)
766 {
767     symbol *sym1, *sym2;
768     int i;
769
770     /* if they have registers in common */
771     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
772         return FALSE ;
773
774     sym1 = OP_SYMBOL(op1);
775     sym2 = OP_SYMBOL(op2);
776
777     if (sym1->nRegs == 0 || sym2->nRegs == 0)
778         return FALSE ;
779
780     for (i = 0 ; i < sym1->nRegs ; i++) {
781         int j;
782         if (!sym1->regs[i])
783             continue ;
784
785         for (j = 0 ; j < sym2->nRegs ;j++ ) {
786             if (!sym2->regs[j])
787                 continue ;
788
789             if (sym2->regs[j] == sym1->regs[i])
790                 return TRUE ;
791         }
792     }
793
794     return FALSE ;
795 }
796
797 /*-----------------------------------------------------------------*/
798 /* operandsEqu - equivalent                                        */
799 /*-----------------------------------------------------------------*/
800 static bool operandsEqu ( operand *op1, operand *op2)
801 {
802     symbol *sym1, *sym2;
803
804     /* if they not symbols */
805     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
806         return FALSE;
807
808     sym1 = OP_SYMBOL(op1);
809     sym2 = OP_SYMBOL(op2);
810
811     /* if both are itemps & one is spilt
812        and the other is not then false */
813     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
814         sym1->isspilt != sym2->isspilt )
815         return FALSE ;
816
817     /* if they are the same */
818     if (sym1 == sym2)
819         return TRUE ;
820
821     if (strcmp(sym1->rname,sym2->rname) == 0)
822         return TRUE;
823
824
825     /* if left is a tmp & right is not */
826     if (IS_ITEMP(op1)  && 
827         !IS_ITEMP(op2) &&
828         sym1->isspilt  &&
829         (sym1->usl.spillLoc == sym2))
830         return TRUE;
831
832     if (IS_ITEMP(op2)  && 
833         !IS_ITEMP(op1) &&
834         sym2->isspilt  &&
835         sym1->level > 0 &&
836         (sym2->usl.spillLoc == sym1))
837         return TRUE ;
838
839     return FALSE ;
840 }
841
842 /*-----------------------------------------------------------------*/
843 /* pic16_sameRegs - two asmops have the same registers                   */
844 /*-----------------------------------------------------------------*/
845 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
846 {
847     int i;
848
849     if (aop1 == aop2)
850         return TRUE ;
851
852     if (aop1->type != AOP_REG ||
853         aop2->type != AOP_REG )
854         return FALSE ;
855
856     if (aop1->size != aop2->size )
857         return FALSE ;
858
859     for (i = 0 ; i < aop1->size ; i++ )
860         if (aop1->aopu.aop_reg[i] !=
861             aop2->aopu.aop_reg[i] )
862             return FALSE ;
863
864     return TRUE ;
865 }
866
867 /*-----------------------------------------------------------------*/
868 /* pic16_aopOp - allocates an asmop for an operand  :                    */
869 /*-----------------------------------------------------------------*/
870 void pic16_aopOp (operand *op, iCode *ic, bool result)
871 {
872     asmop *aop;
873     symbol *sym;
874     int i;
875
876     if (!op)
877         return ;
878
879 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
880
881     /* if this a literal */
882     if (IS_OP_LITERAL(op)) {
883         op->aop = aop = newAsmop(AOP_LIT);
884         aop->aopu.aop_lit = op->operand.valOperand;
885         aop->size = getSize(operandType(op));
886         return;
887     }
888
889     {
890       sym_link *type = operandType(op);
891 #if 0
892       if(IS_PTR_CONST(type))
893 #else
894       if(IS_CODEPTR(type))
895 #endif
896         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
897     }
898
899     /* if already has a asmop then continue */
900     if (op->aop)
901         return ;
902
903     /* if the underlying symbol has a aop */
904     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
905       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
906         op->aop = OP_SYMBOL(op)->aop;
907         return;
908     }
909
910     /* if this is a true symbol */
911     if (IS_TRUE_SYMOP(op)) {    
912         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
913       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
914       return ;
915     }
916
917     /* this is a temporary : this has
918     only four choices :
919     a) register
920     b) spillocation
921     c) rematerialize 
922     d) conditional   
923     e) can be a return use only */
924
925     sym = OP_SYMBOL(op);
926
927         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
928     /* if the type is a conditional */
929     if (sym->regType == REG_CND) {
930         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
931         aop->size = 0;
932         return;
933     }
934
935     /* if it is spilt then two situations
936     a) is rematerialize 
937     b) has a spill location */
938     if (sym->isspilt || sym->nRegs == 0) {
939
940       DEBUGpic16_emitcode(";","%d",__LINE__);
941         /* rematerialize it NOW */
942         if (sym->remat) {
943
944             sym->aop = op->aop = aop =
945                                       aopForRemat (op);
946             aop->size = getSize(sym->type);
947             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
948             return;
949         }
950
951 #if 1
952         if (sym->accuse) {
953             int i;
954             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
955             aop->size = getSize(sym->type);
956             for ( i = 0 ; i < 1 ; i++ ) {
957                 aop->aopu.aop_str[i] = accUse[i];
958 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
959             }
960             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
961             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
962             return;  
963         }
964 #endif
965
966 #if 1
967         if (sym->ruonly ) {
968           /*
969           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
970           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
971           //pic16_allocDirReg (IC_LEFT(ic));
972           aop->size = getSize(sym->type);
973           */
974
975           unsigned i;
976
977           aop = op->aop = sym->aop = newAsmop(AOP_STR);
978           aop->size = getSize(sym->type);
979           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
980             aop->aopu.aop_str[i] = fReturn[i];
981
982           DEBUGpic16_emitcode(";","%d",__LINE__);
983           return;
984         }
985 #endif
986         /* else spill location  */
987         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
988             /* force a new aop if sizes differ */
989             sym->usl.spillLoc->aop = NULL;
990         }
991         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
992                             __FUNCTION__,__LINE__,
993                             sym->usl.spillLoc->rname,
994                             sym->rname, sym->usl.spillLoc->offset);
995
996         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
997         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
998         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
999                                           getSize(sym->type), 
1000                                           sym->usl.spillLoc->offset);
1001         aop->size = getSize(sym->type);
1002
1003         return;
1004     }
1005
1006     {
1007       sym_link *type = operandType(op);
1008 #if 0
1009       if(IS_PTR_CONST(type)) 
1010 #else
1011       if(IS_CODEPTR(type)) 
1012 #endif
1013         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1014     }
1015
1016     /* must be in a register */
1017     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1018     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1019     aop->size = sym->nRegs;
1020     for ( i = 0 ; i < sym->nRegs ;i++)
1021         aop->aopu.aop_reg[i] = sym->regs[i];
1022 }
1023
1024 /*-----------------------------------------------------------------*/
1025 /* pic16_freeAsmop - free up the asmop given to an operand               */
1026 /*----------------------------------------------------------------*/
1027 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1028 {   
1029     asmop *aop ;
1030
1031     if (!op)
1032         aop = aaop;
1033     else 
1034         aop = op->aop;
1035
1036     if (!aop)
1037         return ;
1038
1039     if (aop->freed)
1040         goto dealloc; 
1041
1042     aop->freed = 1;
1043
1044     /* depending on the asmop type only three cases need work AOP_RO
1045        , AOP_R1 && AOP_STK */
1046 #if 0
1047     switch (aop->type) {
1048         case AOP_R0 :
1049             if (_G.r0Pushed ) {
1050                 if (pop) {
1051                     pic16_emitcode ("pop","ar0");     
1052                     _G.r0Pushed--;
1053                 }
1054             }
1055             bitVectUnSetBit(ic->rUsed,R0_IDX);
1056             break;
1057
1058         case AOP_R1 :
1059             if (_G.r1Pushed ) {
1060                 if (pop) {
1061                     pic16_emitcode ("pop","ar1");
1062                     _G.r1Pushed--;
1063                 }
1064             }
1065             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1066             break;
1067
1068         case AOP_STK :
1069         {
1070             int sz = aop->size;    
1071             int stk = aop->aopu.aop_stk + aop->size;
1072             bitVectUnSetBit(ic->rUsed,R0_IDX);
1073             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1074
1075             getFreePtr(ic,&aop,FALSE);
1076             
1077             if (options.stack10bit)
1078             {
1079                 /* I'm not sure what to do here yet... */
1080                 /* #STUB */
1081                 fprintf(stderr, 
1082                         "*** Warning: probably generating bad code for "
1083                         "10 bit stack mode.\n");
1084             }
1085             
1086             if (stk) {
1087                 pic16_emitcode ("mov","a,_bp");
1088                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1089                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1090             } else {
1091                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1092             }
1093
1094             while (sz--) {
1095                 pic16_emitcode("pop","acc");
1096                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1097                 if (!sz) break;
1098                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1099             }
1100             op->aop = aop;
1101             pic16_freeAsmop(op,NULL,ic,TRUE);
1102             if (_G.r0Pushed) {
1103                 pic16_emitcode("pop","ar0");
1104                 _G.r0Pushed--;
1105             }
1106
1107             if (_G.r1Pushed) {
1108                 pic16_emitcode("pop","ar1");
1109                 _G.r1Pushed--;
1110             }       
1111         }
1112     }
1113 #endif
1114
1115 dealloc:
1116     /* all other cases just dealloc */
1117     if (op ) {
1118         op->aop = NULL;
1119         if (IS_SYMOP(op)) {
1120             OP_SYMBOL(op)->aop = NULL;    
1121             /* if the symbol has a spill */
1122             if (SPIL_LOC(op))
1123                 SPIL_LOC(op)->aop = NULL;
1124         }
1125     }
1126 }
1127
1128 /*-----------------------------------------------------------------*/
1129 /* pic16_aopGet - for fetching value of the aop                          */
1130 /*-----------------------------------------------------------------*/
1131 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1132 {
1133     char *s = buffer ;
1134     char *rs;
1135
1136     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1137
1138     /* offset is greater than size then zero */
1139     if (offset > (aop->size - 1) &&
1140         aop->type != AOP_LIT)
1141         return zero;
1142
1143     /* depending on type */
1144     switch (aop->type) {
1145         
1146     case AOP_R0:
1147     case AOP_R1:
1148         DEBUGpic16_emitcode(";","%d",__LINE__);
1149         /* if we need to increment it */       
1150         while (offset > aop->coff) {        
1151             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1152             aop->coff++;
1153         }
1154         
1155         while (offset < aop->coff) {
1156             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1157             aop->coff--;
1158         }
1159         
1160         aop->coff = offset ;
1161         if (aop->paged) {
1162             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1163             return (dname ? "acc" : "a");
1164         }       
1165         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1166         rs = Safe_calloc(1,strlen(s)+1);
1167         strcpy(rs,s);   
1168         return rs;
1169         
1170     case AOP_DPTR:
1171     case AOP_DPTR2:
1172         DEBUGpic16_emitcode(";","%d",__LINE__);
1173     if (aop->type == AOP_DPTR2)
1174     {
1175         genSetDPTR(1);
1176     }
1177     
1178         while (offset > aop->coff) {
1179             pic16_emitcode ("inc","dptr");
1180             aop->coff++;
1181         }
1182         
1183         while (offset < aop->coff) {        
1184             pic16_emitcode("lcall","__decdptr");
1185             aop->coff--;
1186         }
1187         
1188         aop->coff = offset;
1189         if (aop->code) {
1190             pic16_emitcode("clr","a");
1191             pic16_emitcode("movc","a,@a+dptr");
1192         }
1193     else {
1194             pic16_emitcode("movx","a,@dptr");
1195     }
1196             
1197     if (aop->type == AOP_DPTR2)
1198     {
1199         genSetDPTR(0);
1200     }
1201             
1202     return (dname ? "acc" : "a");
1203         
1204         
1205     case AOP_IMMD:
1206         if (bit16) 
1207             sprintf (s,"%s",aop->aopu.aop_immd);
1208         else
1209             if (offset) 
1210                 sprintf(s,"(%s >> %d)",
1211                         aop->aopu.aop_immd,
1212                         offset*8);
1213             else
1214                 sprintf(s,"%s",
1215                         aop->aopu.aop_immd);
1216         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1217         rs = Safe_calloc(1,strlen(s)+1);
1218         strcpy(rs,s);   
1219         return rs;
1220         
1221     case AOP_DIR:
1222       if (offset) {
1223         sprintf(s,"(%s + %d)",
1224                 aop->aopu.aop_dir,
1225                 offset);
1226         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1227       } else
1228             sprintf(s,"%s",aop->aopu.aop_dir);
1229         rs = Safe_calloc(1,strlen(s)+1);
1230         strcpy(rs,s);   
1231         return rs;
1232         
1233     case AOP_REG:
1234       //if (dname) 
1235       //    return aop->aopu.aop_reg[offset]->dname;
1236       //else
1237             return aop->aopu.aop_reg[offset]->name;
1238         
1239     case AOP_CRY:
1240       //pic16_emitcode(";","%d",__LINE__);
1241       return aop->aopu.aop_dir;
1242         
1243     case AOP_ACC:
1244         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1245 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1246 //        assert( 0 );
1247         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1248
1249     case AOP_LIT:
1250         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1251         rs = Safe_calloc(1,strlen(s)+1);
1252         strcpy(rs,s);   
1253         return rs;
1254         
1255     case AOP_STR:
1256         aop->coff = offset ;
1257         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1258             dname)
1259             return "acc";
1260         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1261         
1262         return aop->aopu.aop_str[offset];
1263         
1264     case AOP_PCODE:
1265       {
1266         pCodeOp *pcop = aop->aopu.pcop;
1267         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1268         if(pcop->name) {
1269           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1270           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1271           sprintf(s,"%s", pcop->name);
1272         } else
1273           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1274
1275       }
1276       rs = Safe_calloc(1,strlen(s)+1);
1277       strcpy(rs,s);   
1278       return rs;
1279
1280     }
1281
1282     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1283            "aopget got unsupported aop->type");
1284     exit(0);
1285 }
1286
1287
1288 /*-----------------------------------------------------------------*/
1289 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1290 /*-----------------------------------------------------------------*/
1291 pCodeOp *pic16_popGetTempReg(void)
1292 {
1293   pCodeOp *pcop;
1294   symbol *cfunc;
1295
1296 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1297
1298         cfunc = currFunc;
1299         currFunc = NULL;
1300
1301         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1302         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1303                 PCOR(pcop)->r->wasUsed=1;
1304                 PCOR(pcop)->r->isFree=0;
1305
1306                 /* push value on stack */
1307                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1308         }
1309
1310         currFunc = cfunc;
1311
1312   return pcop;
1313 }
1314
1315 /*-----------------------------------------------------------------*/
1316 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1317 /*-----------------------------------------------------------------*/
1318 void pic16_popReleaseTempReg(pCodeOp *pcop)
1319 {
1320         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1321
1322         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1323                 PCOR(pcop)->r->isFree = 1;
1324                 
1325                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1326         }
1327 }
1328 /*-----------------------------------------------------------------*/
1329 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1330 /*-----------------------------------------------------------------*/
1331 pCodeOp *pic16_popGetLabel(unsigned int key)
1332 {
1333
1334   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1335
1336   if(key>max_key)
1337     max_key = key;
1338
1339   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1340 }
1341
1342 /*-----------------------------------------------------------------*/
1343 /* pic16_popCopyReg - copy a pcode operator                              */
1344 /*-----------------------------------------------------------------*/
1345 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1346 {
1347   pCodeOpReg *pcor;
1348
1349   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1350   pcor->pcop.type = pc->pcop.type;
1351   if(pc->pcop.name) {
1352     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1353       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1354   } else
1355     pcor->pcop.name = NULL;
1356
1357   pcor->r = pc->r;
1358   pcor->rIdx = pc->rIdx;
1359   pcor->r->wasUsed=1;
1360
1361 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1362
1363   return PCOP(pcor);
1364 }
1365
1366 /*-----------------------------------------------------------------*/
1367 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1368 /*-----------------------------------------------------------------*/
1369 pCodeOp *pic16_popGetLit(unsigned int lit)
1370 {
1371   return pic16_newpCodeOpLit(lit);
1372 }
1373
1374 /*-----------------------------------------------------------------*/
1375 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1376 /*-----------------------------------------------------------------*/
1377 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1378 {
1379   return pic16_newpCodeOpLit2(lit, arg2);
1380 }
1381
1382
1383 /*-----------------------------------------------------------------*/
1384 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1385 /*-----------------------------------------------------------------*/
1386 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1387 {
1388   return pic16_newpCodeOpImmd(name, offset,index, 0);
1389 }
1390
1391
1392 /*-----------------------------------------------------------------*/
1393 /* pic16_popGet - asm operator to pcode operator conversion              */
1394 /*-----------------------------------------------------------------*/
1395 pCodeOp *pic16_popGetWithString(char *str)
1396 {
1397   pCodeOp *pcop;
1398
1399
1400   if(!str) {
1401     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1402     exit (1);
1403   }
1404
1405   pcop = pic16_newpCodeOp(str,PO_STR);
1406
1407   return pcop;
1408 }
1409
1410 /*-----------------------------------------------------------------*/
1411 /* pic16_popRegFromString -                                        */
1412 /*-----------------------------------------------------------------*/
1413 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1414 {
1415
1416   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1417   pcop->type = PO_DIR;
1418
1419   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1420   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1421
1422   if(!str)
1423     str = "BAD_STRING";
1424
1425   pcop->name = Safe_calloc(1,strlen(str)+1);
1426   strcpy(pcop->name,str);
1427
1428   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1429
1430   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1431   if(PCOR(pcop)->r == NULL) {
1432 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1433 //              __FUNCTION__, __LINE__, str, size, offset);
1434     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1435
1436         //fprintf(stderr, "allocating new register -> %s\n", str);
1437
1438 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1439   } else {
1440 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1441   }
1442   PCOR(pcop)->instance = offset;
1443
1444   return pcop;
1445 }
1446
1447 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1448 {
1449   pCodeOp *pcop;
1450
1451 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1452
1453         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1454         PCOR(pcop)->rIdx = rIdx;
1455         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1456         PCOR(pcop)->r->isFree = 0;
1457         PCOR(pcop)->r->wasUsed = 1;
1458
1459         pcop->type = PCOR(pcop)->r->pc_type;
1460
1461   return pcop;
1462 }
1463
1464 /*---------------------------------------------------------------------------------*/
1465 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1466 /*                 VR 030601                                                       */
1467 /*---------------------------------------------------------------------------------*/
1468 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1469 {
1470   pCodeOpReg2 *pcop2;
1471   pCodeOp *temp;
1472   
1473         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1474
1475         /* comment the following check, so errors to throw up */
1476 //      if(!pcop2)return NULL;
1477
1478         temp = pic16_popGet(aop_dst, offset);
1479         pcop2->pcop2 = temp;
1480         
1481   return PCOP(pcop2);
1482 }
1483
1484
1485
1486 /*--------------------------------------------------------------------------------.-*/
1487 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1488 /*                  VR 030601 , adapted by Hans Dorn                                */
1489 /*--------------------------------------------------------------------------------.-*/
1490 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1491 {
1492   pCodeOpReg2 *pcop2;
1493  
1494         pcop2 = (pCodeOpReg2 *)src;
1495         pcop2->pcop2 = dst;
1496         
1497         return PCOP(pcop2);
1498 }
1499
1500
1501
1502 /*---------------------------------------------------------------------------------*/
1503 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1504 /*                     movff instruction                                           */
1505 /*---------------------------------------------------------------------------------*/
1506 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1507 {
1508   pCodeOpReg2 *pcop2;
1509
1510         if(!noalloc) {
1511                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1512                 pcop2->pcop2 = pic16_popCopyReg(dst);
1513         } else {
1514                 /* the pCodeOp may be already allocated */
1515                 pcop2 = (pCodeOpReg2 *)(src);
1516                 pcop2->pcop2 = (pCodeOp *)(dst);
1517         }
1518
1519   return PCOP(pcop2);
1520 }
1521
1522
1523 /*-----------------------------------------------------------------*/
1524 /* pic16_popGet - asm operator to pcode operator conversion              */
1525 /*-----------------------------------------------------------------*/
1526 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1527 {
1528   //char *s = buffer ;
1529   char *rs;
1530   pCodeOp *pcop;
1531
1532     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1533     /* offset is greater than
1534     size then zero */
1535
1536 //    if (offset > (aop->size - 1) &&
1537 //        aop->type != AOP_LIT)
1538 //      return NULL;  //zero;
1539
1540     /* depending on type */
1541     switch (aop->type) {
1542         
1543     case AOP_R0:
1544     case AOP_R1:
1545     case AOP_DPTR:
1546     case AOP_DPTR2:
1547         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1548         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1549         assert( 0 );
1550         return NULL;
1551
1552
1553
1554     case AOP_IMMD:
1555       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1556       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1557
1558     case AOP_ACC:
1559       {
1560         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1561
1562         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1563
1564         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1565         
1566         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1567         PCOR(pcop)->rIdx = rIdx;
1568         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1569         PCOR(pcop)->r->wasUsed=1;
1570         PCOR(pcop)->r->isFree=0;
1571
1572         PCOR(pcop)->instance = offset;
1573         pcop->type = PCOR(pcop)->r->pc_type;
1574 //      rs = aop->aopu.aop_reg[offset]->name;
1575 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1576         return pcop;
1577
1578
1579 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1580 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1581
1582 //      assert( 0 );
1583       }
1584         
1585     case AOP_DIR:
1586       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1587       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1588         
1589     case AOP_REG:
1590       {
1591         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1592
1593         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1594         
1595         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1596         PCOR(pcop)->rIdx = rIdx;
1597         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1598         PCOR(pcop)->r->wasUsed=1;
1599         PCOR(pcop)->r->isFree=0;
1600
1601         PCOR(pcop)->instance = offset;
1602         pcop->type = PCOR(pcop)->r->pc_type;
1603         rs = aop->aopu.aop_reg[offset]->name;
1604         DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1605         return pcop;
1606       }
1607
1608     case AOP_CRY:
1609         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1610
1611       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1612       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1613       //if(PCOR(pcop)->r == NULL)
1614       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1615       return pcop;
1616         
1617     case AOP_LIT:
1618         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1619       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1620
1621     case AOP_STR:
1622       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1623       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1624
1625       /*
1626       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1627       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1628       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1629       pcop->type = PCOR(pcop)->r->pc_type;
1630       pcop->name = PCOR(pcop)->r->name;
1631
1632       return pcop;
1633       */
1634
1635     case AOP_PCODE:
1636       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1637                           __LINE__, 
1638                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1639       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1640 #if 1
1641         switch( aop->aopu.pcop->type ) {
1642                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1643                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1644                 default:
1645                         assert( 0 );    /* should never reach here */;
1646         }
1647 #else
1648       PCOI(pcop)->offset = offset;
1649 #endif
1650       return pcop;
1651     }
1652
1653     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1654            "pic16_popGet got unsupported aop->type");
1655     exit(0);
1656 }
1657 /*-----------------------------------------------------------------*/
1658 /* pic16_aopPut - puts a string for a aop                                */
1659 /*-----------------------------------------------------------------*/
1660 void pic16_aopPut (asmop *aop, char *s, int offset)
1661 {
1662     char *d = buffer ;
1663     symbol *lbl ;
1664
1665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1666
1667     if (aop->size && offset > ( aop->size - 1)) {
1668         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1669                "pic16_aopPut got offset > aop->size");
1670         exit(0);
1671     }
1672
1673     /* will assign value to value */
1674     /* depending on where it is ofcourse */
1675     switch (aop->type) {
1676     case AOP_DIR:
1677       if (offset) {
1678         sprintf(d,"(%s + %d)",
1679                 aop->aopu.aop_dir,offset);
1680         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1681
1682       } else
1683             sprintf(d,"%s",aop->aopu.aop_dir);
1684         
1685         if (strcmp(d,s)) {
1686           DEBUGpic16_emitcode(";","%d",__LINE__);
1687           if(strcmp(s,"W"))
1688             pic16_emitcode("movf","%s,w",s);
1689           pic16_emitcode("movwf","%s",d);
1690
1691           if(strcmp(s,"W")) {
1692             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1693             if(offset >= aop->size) {
1694               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1695               break;
1696             } else
1697               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1698           }
1699
1700           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1701
1702
1703         }
1704         break;
1705         
1706     case AOP_REG:
1707       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1708         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1709           /*
1710             if (*s == '@'           ||
1711                 strcmp(s,"r0") == 0 ||
1712                 strcmp(s,"r1") == 0 ||
1713                 strcmp(s,"r2") == 0 ||
1714                 strcmp(s,"r3") == 0 ||
1715                 strcmp(s,"r4") == 0 ||
1716                 strcmp(s,"r5") == 0 ||
1717                 strcmp(s,"r6") == 0 || 
1718                 strcmp(s,"r7") == 0 )
1719                 pic16_emitcode("mov","%s,%s  ; %d",
1720                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1721             else
1722           */
1723
1724           if(strcmp(s,"W")==0 )
1725             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1726
1727           pic16_emitcode("movwf","%s",
1728                    aop->aopu.aop_reg[offset]->name);
1729
1730           if(strcmp(s,zero)==0) {
1731             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1732
1733           } else if(strcmp(s,"W")==0) {
1734             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1735             pcop->type = PO_GPR_REGISTER;
1736
1737             PCOR(pcop)->rIdx = -1;
1738             PCOR(pcop)->r = NULL;
1739
1740             DEBUGpic16_emitcode(";","%d",__LINE__);
1741             pcop->name = Safe_strdup(s);
1742             pic16_emitpcode(POC_MOVFW,pcop);
1743             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1744           } else if(strcmp(s,one)==0) {
1745             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1746             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1747           } else {
1748             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1749           }
1750         }
1751         break;
1752         
1753     case AOP_DPTR:
1754     case AOP_DPTR2:
1755     
1756     if (aop->type == AOP_DPTR2)
1757     {
1758         genSetDPTR(1);
1759     }
1760     
1761         if (aop->code) {
1762             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1763                    "pic16_aopPut writting to code space");
1764             exit(0);
1765         }
1766         
1767         while (offset > aop->coff) {
1768             aop->coff++;
1769             pic16_emitcode ("inc","dptr");
1770         }
1771         
1772         while (offset < aop->coff) {
1773             aop->coff-- ;
1774             pic16_emitcode("lcall","__decdptr");
1775         }
1776         
1777         aop->coff = offset;
1778         
1779         /* if not in accumulater */
1780         MOVA(s);        
1781         
1782         pic16_emitcode ("movx","@dptr,a");
1783         
1784     if (aop->type == AOP_DPTR2)
1785     {
1786         genSetDPTR(0);
1787     }
1788         break;
1789         
1790     case AOP_R0:
1791     case AOP_R1:
1792         while (offset > aop->coff) {
1793             aop->coff++;
1794             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1795         }
1796         while (offset < aop->coff) {
1797             aop->coff-- ;
1798             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1799         }
1800         aop->coff = offset;
1801         
1802         if (aop->paged) {
1803             MOVA(s);           
1804             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1805             
1806         } else
1807             if (*s == '@') {
1808                 MOVA(s);
1809                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1810             } else
1811                 if (strcmp(s,"r0") == 0 ||
1812                     strcmp(s,"r1") == 0 ||
1813                     strcmp(s,"r2") == 0 ||
1814                     strcmp(s,"r3") == 0 ||
1815                     strcmp(s,"r4") == 0 ||
1816                     strcmp(s,"r5") == 0 ||
1817                     strcmp(s,"r6") == 0 || 
1818                     strcmp(s,"r7") == 0 ) {
1819                     char buffer[10];
1820                     sprintf(buffer,"a%s",s);
1821                     pic16_emitcode("mov","@%s,%s",
1822                              aop->aopu.aop_ptr->name,buffer);
1823                 } else
1824                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1825         
1826         break;
1827         
1828     case AOP_STK:
1829         if (strcmp(s,"a") == 0)
1830             pic16_emitcode("push","acc");
1831         else
1832             pic16_emitcode("push","%s",s);
1833         
1834         break;
1835         
1836     case AOP_CRY:
1837         /* if bit variable */
1838         if (!aop->aopu.aop_dir) {
1839             pic16_emitcode("clr","a");
1840             pic16_emitcode("rlc","a");
1841         } else {
1842             if (s == zero) 
1843                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1844             else
1845                 if (s == one)
1846                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1847                 else
1848                     if (!strcmp(s,"c"))
1849                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1850                     else {
1851                         lbl = newiTempLabel(NULL);
1852                         
1853                         if (strcmp(s,"a")) {
1854                             MOVA(s);
1855                         }
1856                         pic16_emitcode("clr","c");
1857                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1858                         pic16_emitcode("cpl","c");
1859                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1860                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1861                     }
1862         }
1863         break;
1864         
1865     case AOP_STR:
1866         aop->coff = offset;
1867         if (strcmp(aop->aopu.aop_str[offset],s))
1868             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1869         break;
1870         
1871     case AOP_ACC:
1872         aop->coff = offset;
1873         if (!offset && (strcmp(s,"acc") == 0))
1874             break;
1875         
1876         if (strcmp(aop->aopu.aop_str[offset],s))
1877             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1878         break;
1879
1880     default :
1881         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1882                "pic16_aopPut got unsupported aop->type");
1883         exit(0);    
1884     }    
1885
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1890 /*-----------------------------------------------------------------*/
1891 static void mov2w (asmop *aop, int offset)
1892 {
1893
1894   if(!aop)
1895     return;
1896
1897   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1898
1899   if ( aop->type == AOP_PCODE ||
1900        aop->type == AOP_LIT )
1901     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1902   else
1903     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1904
1905 }
1906
1907
1908 /* push pcop into stack */
1909 void pic16_pushpCodeOp(pCodeOp *pcop)
1910 {
1911 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1912         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1913 }
1914
1915 /* pop pcop from stack */
1916 void pic16_poppCodeOp(pCodeOp *pcop)
1917 {
1918         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1919 }
1920
1921
1922 /*-----------------------------------------------------------------*/
1923 /* pushw - pushes wreg to stack                                    */
1924 /*-----------------------------------------------------------------*/
1925 void pushw(void)
1926 {
1927         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1928         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1929 }
1930
1931                 
1932 /*-----------------------------------------------------------------*/
1933 /* pushaop - pushes aop to stack                                   */
1934 /*-----------------------------------------------------------------*/
1935 void pushaop(asmop *aop, int offset)
1936 {
1937         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1938         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1939 }
1940
1941 /*-----------------------------------------------------------------*/
1942 /* popaop - pops aop from stack                                    */
1943 /*-----------------------------------------------------------------*/
1944 void popaop(asmop *aop, int offset)
1945 {
1946         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1947         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1948 }
1949
1950 void popaopidx(asmop *aop, int offset, int index)
1951 {
1952   int ofs=1;
1953
1954         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1955
1956         if(STACK_MODEL_LARGE)ofs++;
1957
1958         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1959         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1960 }
1961
1962 /*-----------------------------------------------------------------*/
1963 /* reAdjustPreg - points a register back to where it should        */
1964 /*-----------------------------------------------------------------*/
1965 static void reAdjustPreg (asmop *aop)
1966 {
1967     int size ;
1968
1969     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1970     aop->coff = 0;
1971     if ((size = aop->size) <= 1)
1972         return ;
1973     size-- ;
1974     switch (aop->type) {
1975         case AOP_R0 :
1976         case AOP_R1 :
1977             while (size--)
1978                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1979             break;          
1980         case AOP_DPTR :
1981         case AOP_DPTR2:
1982             if (aop->type == AOP_DPTR2)
1983             {
1984                 genSetDPTR(1);
1985             } 
1986             while (size--)
1987             {
1988                 pic16_emitcode("lcall","__decdptr");
1989             }
1990                 
1991             if (aop->type == AOP_DPTR2)
1992             {
1993                 genSetDPTR(0);
1994             }                
1995             break;  
1996
1997     }   
1998
1999 }
2000
2001
2002 #if 0
2003 /*-----------------------------------------------------------------*/
2004 /* opIsGptr: returns non-zero if the passed operand is             */   
2005 /* a generic pointer type.                                         */
2006 /*-----------------------------------------------------------------*/ 
2007 static int opIsGptr(operand *op)
2008 {
2009     sym_link *type = operandType(op);
2010     
2011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2012     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2013     {
2014         return 1;
2015     }
2016     return 0;        
2017 }
2018 #endif
2019
2020 /*-----------------------------------------------------------------*/
2021 /* pic16_getDataSize - get the operand data size                         */
2022 /*-----------------------------------------------------------------*/
2023 int pic16_getDataSize(operand *op)
2024 {
2025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2026
2027
2028     return AOP_SIZE(op);
2029
2030     // tsd- in the pic port, the genptr size is 1, so this code here
2031     // fails. ( in the 8051 port, the size was 4).
2032 #if 0
2033     int size;
2034     size = AOP_SIZE(op);
2035     if (size == GPTRSIZE)
2036     {
2037         sym_link *type = operandType(op);
2038         if (IS_GENPTR(type))
2039         {
2040             /* generic pointer; arithmetic operations
2041              * should ignore the high byte (pointer type).
2042              */
2043             size--;
2044     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2045         }
2046     }
2047     return size;
2048 #endif
2049 }
2050
2051 /*-----------------------------------------------------------------*/
2052 /* pic16_outAcc - output Acc                                             */
2053 /*-----------------------------------------------------------------*/
2054 void pic16_outAcc(operand *result)
2055 {
2056   int size,offset;
2057   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2058   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2059
2060
2061   size = pic16_getDataSize(result);
2062   if(size){
2063     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2064     size--;
2065     offset = 1;
2066     /* unsigned or positive */
2067     while(size--)
2068       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2069   }
2070
2071 }
2072
2073 /*-----------------------------------------------------------------*/
2074 /* pic16_outBitC - output a bit C                                        */
2075 /*-----------------------------------------------------------------*/
2076 void pic16_outBitC(operand *result)
2077 {
2078
2079     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2080     /* if the result is bit */
2081     if (AOP_TYPE(result) == AOP_CRY) 
2082         pic16_aopPut(AOP(result),"c",0);
2083     else {
2084         pic16_emitcode("clr","a  ; %d", __LINE__);
2085         pic16_emitcode("rlc","a");
2086         pic16_outAcc(result);
2087     }
2088 }
2089
2090 /*-----------------------------------------------------------------*/
2091 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2092 /*-----------------------------------------------------------------*/
2093 void pic16_toBoolean(operand *oper)
2094 {
2095     int size = AOP_SIZE(oper) - 1;
2096     int offset = 1;
2097
2098     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2099
2100     if ( AOP_TYPE(oper) != AOP_ACC) {
2101       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2102     }
2103     while (size--) {
2104       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2105     }
2106 }
2107
2108
2109 #if !defined(GEN_Not)
2110 /*-----------------------------------------------------------------*/
2111 /* genNot - generate code for ! operation                          */
2112 /*-----------------------------------------------------------------*/
2113 static void pic16_genNot (iCode *ic)
2114 {
2115   symbol *tlbl;
2116   int size;
2117
2118   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2119   /* assign asmOps to operand & result */
2120   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2121   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2122
2123   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2124   /* if in bit space then a special case */
2125   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2126     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2127       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2128       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2129     } else {
2130       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2131       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2132       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2133     }
2134     goto release;
2135   }
2136
2137   size = AOP_SIZE(IC_LEFT(ic));
2138   if(size == 1) {
2139     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2140     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2141     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2142     goto release;
2143   }
2144   pic16_toBoolean(IC_LEFT(ic));
2145
2146   tlbl = newiTempLabel(NULL);
2147   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2148   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2149   pic16_outBitC(IC_RESULT(ic));
2150
2151  release:    
2152   /* release the aops */
2153   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2154   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2155 }
2156 #endif
2157
2158
2159 #if !defined(GEN_Cpl)
2160 /*-----------------------------------------------------------------*/
2161 /* genCpl - generate code for complement                           */
2162 /*-----------------------------------------------------------------*/
2163 static void pic16_genCpl (iCode *ic)
2164 {
2165     int offset = 0;
2166     int size ;
2167
2168
2169     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2170     /* assign asmOps to operand & result */
2171     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2172     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2173
2174     /* if both are in bit space then 
2175     a special case */
2176     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2177         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2178
2179         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2180         pic16_emitcode("cpl","c"); 
2181         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2182         goto release; 
2183     } 
2184
2185     size = AOP_SIZE(IC_RESULT(ic));
2186     while (size--) {
2187 /*
2188         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2189         MOVA(l);       
2190         pic16_emitcode("cpl","a");
2191         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2192 */
2193         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2194               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2195         } else {
2196                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2197                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2198         }
2199         offset++;
2200
2201     }
2202
2203
2204 release:
2205     /* release the aops */
2206     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2207     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2208 }
2209 #endif
2210
2211 /*-----------------------------------------------------------------*/
2212 /* genUminusFloat - unary minus for floating points                */
2213 /*-----------------------------------------------------------------*/
2214 static void genUminusFloat(operand *op,operand *result)
2215 {
2216     int size ,offset =0 ;
2217     char *l;
2218
2219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2220     /* for this we just need to flip the 
2221     first it then copy the rest in place */
2222     size = AOP_SIZE(op) - 1;
2223     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2224
2225     MOVA(l);    
2226
2227     pic16_emitcode("cpl","acc.7");
2228     pic16_aopPut(AOP(result),"a",3);    
2229
2230     while(size--) {
2231         pic16_aopPut(AOP(result),
2232                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2233                offset);
2234         offset++;
2235     }          
2236 }
2237
2238 /*-----------------------------------------------------------------*/
2239 /* genUminus - unary minus code generation                         */
2240 /*-----------------------------------------------------------------*/
2241 static void genUminus (iCode *ic)
2242 {
2243   int size, i;
2244   sym_link *optype, *rtype;
2245
2246
2247   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2248   /* assign asmops */
2249   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2250   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2251
2252   /* if both in bit space then special
2253      case */
2254   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2255       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2256
2257     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2258     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2259     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2260
2261     goto release; 
2262   } 
2263
2264   optype = operandType(IC_LEFT(ic));
2265   rtype = operandType(IC_RESULT(ic));
2266
2267   /* if float then do float stuff */
2268   if (IS_FLOAT(optype)) {
2269     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2270     goto release;
2271   }
2272
2273   /* otherwise subtract from zero by taking the 2's complement */
2274   size = AOP_SIZE(IC_LEFT(ic));
2275
2276   for(i=0; i<size; i++) {
2277     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2278       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2279     else {
2280       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2282     }
2283   }
2284
2285   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2286   for(i=1; i<size; i++) {
2287     emitSKPNZ;
2288     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2289   }
2290
2291  release:
2292   /* release the aops */
2293   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2294   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2295 }
2296
2297 /*-----------------------------------------------------------------*/
2298 /* saveRegisters - will look for a call and save the registers     */
2299 /*-----------------------------------------------------------------*/
2300 static void saveRegisters(iCode *lic) 
2301 {
2302     int i;
2303     iCode *ic;
2304     bitVect *rsave;
2305     sym_link *dtype;
2306
2307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2308     /* look for call */
2309     for (ic = lic ; ic ; ic = ic->next) 
2310         if (ic->op == CALL || ic->op == PCALL)
2311             break;
2312
2313     if (!ic) {
2314         fprintf(stderr,"found parameter push with no function call\n");
2315         return ;
2316     }
2317
2318     /* if the registers have been saved already then
2319     do nothing */
2320     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2321         return ;
2322
2323     /* find the registers in use at this time 
2324     and push them away to safety */
2325     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2326                           ic->rUsed);
2327
2328     ic->regsSaved = 1;
2329     if (options.useXstack) {
2330         if (bitVectBitValue(rsave,R0_IDX))
2331             pic16_emitcode("mov","b,r0");
2332         pic16_emitcode("mov","r0,%s",spname);
2333         for (i = 0 ; i < pic16_nRegs ; i++) {
2334             if (bitVectBitValue(rsave,i)) {
2335                 if (i == R0_IDX)
2336                     pic16_emitcode("mov","a,b");
2337                 else
2338                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2339                 pic16_emitcode("movx","@r0,a");
2340                 pic16_emitcode("inc","r0");
2341             }
2342         }
2343         pic16_emitcode("mov","%s,r0",spname);
2344         if (bitVectBitValue(rsave,R0_IDX))
2345             pic16_emitcode("mov","r0,b");           
2346     }// else
2347     //for (i = 0 ; i < pic16_nRegs ; i++) {
2348     //    if (bitVectBitValue(rsave,i))
2349     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2350     //}
2351
2352     dtype = operandType(IC_LEFT(ic));
2353     if (currFunc && dtype && 
2354         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2355         IFFUNC_ISISR(currFunc->type) &&
2356         !ic->bankSaved) 
2357
2358         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2359
2360 }
2361 /*-----------------------------------------------------------------*/
2362 /* unsaveRegisters - pop the pushed registers                      */
2363 /*-----------------------------------------------------------------*/
2364 static void unsaveRegisters (iCode *ic)
2365 {
2366     int i;
2367     bitVect *rsave;
2368
2369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2370     /* find the registers in use at this time 
2371     and push them away to safety */
2372     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2373                           ic->rUsed);
2374     
2375     if (options.useXstack) {
2376         pic16_emitcode("mov","r0,%s",spname);   
2377         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2378             if (bitVectBitValue(rsave,i)) {
2379                 pic16_emitcode("dec","r0");
2380                 pic16_emitcode("movx","a,@r0");
2381                 if (i == R0_IDX)
2382                     pic16_emitcode("mov","b,a");
2383                 else
2384                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2385             }       
2386
2387         }
2388         pic16_emitcode("mov","%s,r0",spname);
2389         if (bitVectBitValue(rsave,R0_IDX))
2390             pic16_emitcode("mov","r0,b");
2391     } //else
2392     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2393     //    if (bitVectBitValue(rsave,i))
2394     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2395     //}
2396
2397 }  
2398
2399 #if 0  // patch 14
2400 /*-----------------------------------------------------------------*/
2401 /* pushSide -                                                      */
2402 /*-----------------------------------------------------------------*/
2403 static void pushSide(operand * oper, int size)
2404 {
2405         int offset = 0;
2406     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2407         while (size--) {
2408                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2409                 if (AOP_TYPE(oper) != AOP_REG &&
2410                     AOP_TYPE(oper) != AOP_DIR &&
2411                     strcmp(l,"a") ) {
2412                         pic16_emitcode("mov","a,%s",l);
2413                         pic16_emitcode("push","acc");
2414                 } else
2415                         pic16_emitcode("push","%s",l);
2416         }
2417 }
2418 #endif // patch 14
2419
2420 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2421 {
2422 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2423
2424         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2425                 pic16_emitpcode(POC_MOVFW, src);
2426                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2427         } else {
2428                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2429                         src, pic16_popGet(AOP(op), offset)));
2430         }
2431 }
2432
2433
2434 /*-----------------------------------------------------------------*/
2435 /* assignResultValue - assign results to oper, rescall==1 is       */
2436 /*                     called from genCall() or genPCall()         */
2437 /*-----------------------------------------------------------------*/
2438 static void assignResultValue(operand * oper, int rescall)
2439 {
2440   int size = AOP_SIZE(oper);
2441
2442         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2443         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2444
2445         if(rescall) {
2446                 /* assign result from a call/pcall function() */
2447                 
2448                 /* function results are stored in a special order,
2449                  * see top of file with Function return policy, or manual */
2450
2451                 if(size <= 4) {
2452                         /* 8-bits, result in WREG */
2453                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2454                         
2455                         if(size>1) {
2456                                 /* 16-bits, result in PRODL:WREG */
2457                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2458                         }
2459                         
2460                         if(size>2) {
2461                                 /* 24-bits, result in PRODH:PRODL:WREG */
2462                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2463                         }
2464                         
2465                         if(size>3) {
2466                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2467                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2468                         }
2469                 } else {
2470                         /* >32-bits, result on stack, and FSR0 points to beginning.
2471                          * Fix stack when done */
2472                          
2473                         while (size--) {
2474 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2475 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2476                 
2477                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2478                                 GpsuedoStkPtr++;
2479                         }
2480                         
2481                         /* fix stack */
2482                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2483                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2484                         if(STACK_MODEL_LARGE) {
2485                                 emitSKPNC;
2486                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2487                         }
2488                 }                       
2489         } else {        
2490                 if(!GpsuedoStkPtr) {
2491 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2492                         /* The last byte in the assignment is in W */
2493                         size--;
2494                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2495                         GpsuedoStkPtr++;
2496                 }
2497
2498                 while (size--) {
2499 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2500 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2501                 
2502                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2503                         GpsuedoStkPtr++;
2504
2505 #if 0
2506 #if STACK_SUPPORT
2507                 if(!USE_STACK)
2508                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2509 #else
2510                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2511 #endif
2512 #endif
2513
2514                 }
2515         }
2516                 
2517 }
2518
2519
2520 /*-----------------------------------------------------------------*/
2521 /* genIpush - genrate code for pushing this gets a little complex  */
2522 /*-----------------------------------------------------------------*/
2523 static void genIpush (iCode *ic)
2524 {
2525
2526   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2527 #if 0
2528     int size, offset = 0 ;
2529     char *l;
2530
2531
2532     /* if this is not a parm push : ie. it is spill push 
2533     and spill push is always done on the local stack */
2534     if (!ic->parmPush) {
2535
2536         /* and the item is spilt then do nothing */
2537         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2538             return ;
2539
2540         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2541         size = AOP_SIZE(IC_LEFT(ic));
2542         /* push it on the stack */
2543         while(size--) {
2544             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2545             if (*l == '#') {
2546                 MOVA(l);
2547                 l = "acc";
2548             }
2549             pic16_emitcode("push","%s",l);
2550         }
2551         return ;        
2552     }
2553
2554     /* this is a paramter push: in this case we call
2555     the routine to find the call and save those
2556     registers that need to be saved */   
2557     saveRegisters(ic);
2558
2559     /* then do the push */
2560     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2561
2562
2563         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2564     size = AOP_SIZE(IC_LEFT(ic));
2565
2566     while (size--) {
2567         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2568         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2569             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2570             strcmp(l,"a") ) {
2571             pic16_emitcode("mov","a,%s",l);
2572             pic16_emitcode("push","acc");
2573         } else
2574             pic16_emitcode("push","%s",l);
2575     }       
2576
2577     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2578 #endif
2579 }
2580
2581 /*-----------------------------------------------------------------*/
2582 /* genIpop - recover the registers: can happen only for spilling   */
2583 /*-----------------------------------------------------------------*/
2584 static void genIpop (iCode *ic)
2585 {
2586   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2587 #if 0
2588     int size,offset ;
2589
2590
2591     /* if the temp was not pushed then */
2592     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2593         return ;
2594
2595     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2596     size = AOP_SIZE(IC_LEFT(ic));
2597     offset = (size-1);
2598     while (size--) 
2599         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2600                                    FALSE,TRUE));
2601
2602     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2603 #endif
2604 }
2605
2606 /*-----------------------------------------------------------------*/
2607 /* unsaverbank - restores the resgister bank from stack            */
2608 /*-----------------------------------------------------------------*/
2609 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2610 {
2611   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2612 #if 0
2613     int i;
2614     asmop *aop ;
2615     regs *r = NULL;
2616
2617     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2618     if (popPsw) {
2619         if (options.useXstack) {
2620             aop = newAsmop(0);
2621             r = getFreePtr(ic,&aop,FALSE);
2622             
2623             
2624             pic16_emitcode("mov","%s,_spx",r->name);
2625             pic16_emitcode("movx","a,@%s",r->name);
2626             pic16_emitcode("mov","psw,a");
2627             pic16_emitcode("dec","%s",r->name);
2628             
2629         }else
2630             pic16_emitcode ("pop","psw");
2631     }
2632
2633     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2634         if (options.useXstack) {       
2635             pic16_emitcode("movx","a,@%s",r->name);
2636             //pic16_emitcode("mov","(%s+%d),a",
2637             //       regspic16[i].base,8*bank+regspic16[i].offset);
2638             pic16_emitcode("dec","%s",r->name);
2639
2640         } else 
2641           pic16_emitcode("pop",""); //"(%s+%d)",
2642         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2643     }
2644
2645     if (options.useXstack) {
2646
2647         pic16_emitcode("mov","_spx,%s",r->name);
2648         pic16_freeAsmop(NULL,aop,ic,TRUE);
2649
2650     }
2651 #endif 
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* saverbank - saves an entire register bank on the stack          */
2656 /*-----------------------------------------------------------------*/
2657 static void saverbank (int bank, iCode *ic, bool pushPsw)
2658 {
2659   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2660 #if 0
2661     int i;
2662     asmop *aop ;
2663     regs *r = NULL;
2664
2665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2666     if (options.useXstack) {
2667
2668         aop = newAsmop(0);
2669         r = getFreePtr(ic,&aop,FALSE);  
2670         pic16_emitcode("mov","%s,_spx",r->name);
2671
2672     }
2673
2674     for (i = 0 ; i < pic16_nRegs ;i++) {
2675         if (options.useXstack) {
2676             pic16_emitcode("inc","%s",r->name);
2677             //pic16_emitcode("mov","a,(%s+%d)",
2678             //         regspic16[i].base,8*bank+regspic16[i].offset);
2679             pic16_emitcode("movx","@%s,a",r->name);           
2680         } else 
2681           pic16_emitcode("push","");// "(%s+%d)",
2682                      //regspic16[i].base,8*bank+regspic16[i].offset);
2683     }
2684     
2685     if (pushPsw) {
2686         if (options.useXstack) {
2687             pic16_emitcode("mov","a,psw");
2688             pic16_emitcode("movx","@%s,a",r->name);     
2689             pic16_emitcode("inc","%s",r->name);
2690             pic16_emitcode("mov","_spx,%s",r->name);       
2691             pic16_freeAsmop (NULL,aop,ic,TRUE);
2692             
2693         } else
2694             pic16_emitcode("push","psw");
2695         
2696         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2697     }
2698     ic->bankSaved = 1;
2699 #endif
2700 }
2701
2702
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genCall - generates a call statement                            */
2706 /*-----------------------------------------------------------------*/
2707 static void genCall (iCode *ic)
2708 {
2709   sym_link *dtype;   
2710   int stackParms=0;
2711   
2712         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2713
2714         /* if caller saves & we have not saved then */
2715         if (!ic->regsSaved)
2716                 saveRegisters(ic);
2717
2718         /* if we are calling a function that is not using
2719          * the same register bank then we need to save the
2720          * destination registers on the stack */
2721         dtype = operandType(IC_LEFT(ic));
2722         if (currFunc && dtype && 
2723                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2724                 IFFUNC_ISISR(currFunc->type) &&
2725                 !ic->bankSaved) 
2726
2727                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2728
2729         /* if send set is not empty the assign */
2730         if (_G.sendSet) {
2731           iCode *sic;
2732
2733                 /* For the Pic port, there is no data stack.
2734                  * So parameters passed to functions are stored
2735                  * in registers. (The pCode optimizer will get
2736                  * rid of most of these :). */
2737
2738           int psuedoStkPtr=-1; 
2739           int firstTimeThruLoop = 1;
2740
2741                 _G.sendSet = reverseSet(_G.sendSet);
2742
2743                 /* First figure how many parameters are getting passed */
2744                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2745                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2746                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2747                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2748                 }
2749
2750                 stackParms = psuedoStkPtr;
2751
2752                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2753                   int size, offset = 0;
2754
2755                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2756                         size = AOP_SIZE(IC_LEFT(sic));
2757
2758                         while (size--) {
2759                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2760                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2761                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2762
2763                                 if(!firstTimeThruLoop) {
2764                                         /* If this is not the first time we've been through the loop
2765                                          * then we need to save the parameter in a temporary
2766                                          * register. The last byte of the last parameter is
2767                                          * passed in W. */
2768
2769                                         pushw();
2770                                         --psuedoStkPtr;         // sanity check
2771                                 }
2772                         
2773                                 firstTimeThruLoop=0;
2774
2775                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2776                                 offset++;
2777                         }
2778                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2779                 }
2780                 _G.sendSet = NULL;
2781         }
2782
2783         /* make the call */
2784         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2785                         OP_SYMBOL(IC_LEFT(ic))->rname :
2786                         OP_SYMBOL(IC_LEFT(ic))->name));
2787
2788         GpsuedoStkPtr=0;
2789         /* if we need assign a result value */
2790         if ((IS_ITEMP(IC_RESULT(ic)) && 
2791                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2792                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2793                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2794
2795                 _G.accInUse++;
2796                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2797                 _G.accInUse--;
2798
2799                 assignResultValue(IC_RESULT(ic), 1);
2800
2801                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2802                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2803                 
2804                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2805         }
2806
2807         if(stackParms>0) {
2808                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2809                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2810                 if(STACK_MODEL_LARGE) {
2811                         emitSKPNC;
2812                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2813                 }
2814         }
2815
2816         /* adjust the stack for parameters if required */
2817 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2818
2819         if (ic->parmBytes) {
2820           int i;
2821
2822                 if (ic->parmBytes > 3) {
2823                         pic16_emitcode("mov","a,%s",spname);
2824                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2825                         pic16_emitcode("mov","%s,a",spname);
2826                 } else 
2827                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2828                                 pic16_emitcode("dec","%s",spname);
2829         }
2830
2831 #if 0
2832         /* if register bank was saved then pop them */
2833         if (ic->bankSaved)
2834                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2835
2836         /* if we hade saved some registers then unsave them */
2837         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2838                 unsaveRegisters (ic);
2839 #endif
2840 }
2841
2842
2843
2844 /*-----------------------------------------------------------------*/   // patch 14
2845 /* genPcall - generates a call by pointer statement                */
2846 /*-----------------------------------------------------------------*/
2847
2848 // new version, created from genCall
2849
2850 static void genPcall (iCode *ic)
2851 {
2852   sym_link *dtype;   
2853   int stackParms=0;
2854   symbol *retlbl = newiTempLabel(NULL);
2855   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2856   
2857         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2858
2859         /* if caller saves & we have not saved then */
2860         if (!ic->regsSaved)
2861                 saveRegisters(ic);
2862
2863         /* if we are calling a function that is not using
2864          * the same register bank then we need to save the
2865          * destination registers on the stack */
2866         dtype = operandType(IC_LEFT(ic));
2867         if (currFunc && dtype && 
2868                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2869                 IFFUNC_ISISR(currFunc->type) &&
2870                 !ic->bankSaved) 
2871
2872                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2873
2874         /* if send set is not empty the assign */
2875         if (_G.sendSet) {
2876           iCode *sic;
2877
2878                 /* For the Pic port, there is no data stack.
2879                  * So parameters passed to functions are stored
2880                  * in registers. (The pCode optimizer will get
2881                  * rid of most of these :). */
2882
2883           int psuedoStkPtr=-1; 
2884           int firstTimeThruLoop = 1;
2885
2886                 _G.sendSet = reverseSet(_G.sendSet);
2887
2888                 /* First figure how many parameters are getting passed */
2889                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2890                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2891                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2892                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2893                 }
2894
2895                 stackParms = psuedoStkPtr;
2896
2897                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2898                   int size, offset = 0;
2899
2900                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2901                         size = AOP_SIZE(IC_LEFT(sic));
2902
2903                         while (size--) {
2904                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2905                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2906                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2907
2908                                 if(!firstTimeThruLoop) {
2909                                         /* If this is not the first time we've been through the loop
2910                                          * then we need to save the parameter in a temporary
2911                                          * register. The last byte of the last parameter is
2912                                          * passed in W. */
2913
2914                                         pushw();
2915                                         --psuedoStkPtr;         // sanity check
2916                                 }
2917                         
2918                                 firstTimeThruLoop=0;
2919
2920                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2921                                 offset++;
2922                         }
2923                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2924                 }
2925                 _G.sendSet = NULL;
2926         }
2927
2928         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2929
2930         // push return address
2931         // push $ on return stack, then replace with retlbl
2932
2933         // Note: retlbl is supplied as dummy operand to PUSH
2934         // This has the nice side effect of keeping the label from being optimized out :o)
2935         pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));      
2936
2937         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2938         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2939         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2940         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2941         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2942         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2943
2944         /* make the call by writing the pointer into pc */
2945 // FIXME Disabled writes to PCLATU because of gpsim problems
2946 #if 0
2947         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2948 #else
2949         fprintf(stderr,
2950 "WARNING: (%s:%d) PCLATU is not written because of gpsim problems\n\
2951 Correct this as soon as gpsim bug is fixed\n", __FILE__, __LINE__);
2952 #endif
2953  
2954         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2955         // note: MOVFF to PCL not allowed
2956         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2957         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2958
2959         /* return address is here: (X) */
2960         pic16_emitpLabel(retlbl->key);
2961
2962         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2963
2964         GpsuedoStkPtr=0;
2965         /* if we need assign a result value */
2966         if ((IS_ITEMP(IC_RESULT(ic)) && 
2967                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2968                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2969                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2970
2971                 _G.accInUse++;
2972                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2973                 _G.accInUse--;
2974
2975                 assignResultValue(IC_RESULT(ic), 1);
2976
2977                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2978                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2979                 
2980                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2981         }
2982
2983         if(stackParms>0) {
2984                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2985                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2986                 if(STACK_MODEL_LARGE) {
2987                         emitSKPNC;
2988                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2989                 }
2990         }
2991
2992         /* adjust the stack for parameters if required */
2993 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2994
2995         if (ic->parmBytes) {
2996           int i;
2997
2998                 if (ic->parmBytes > 3) {
2999                         pic16_emitcode("mov","a,%s",spname);
3000                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3001                         pic16_emitcode("mov","%s,a",spname);
3002                 } else 
3003                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3004                                 pic16_emitcode("dec","%s",spname);
3005         }
3006
3007         /* if register bank was saved then pop them */
3008         if (ic->bankSaved)
3009                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3010
3011         /* if we hade saved some registers then unsave them */
3012         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3013                 unsaveRegisters (ic);
3014 }
3015
3016
3017 #if 0                                                                           // patch 14
3018 // old version, kept for reference
3019
3020 /*-----------------------------------------------------------------*/
3021 /* genPcall - generates a call by pointer statement                */
3022 /*-----------------------------------------------------------------*/
3023 static void genPcall (iCode *ic)
3024 {
3025     sym_link *dtype;
3026     symbol *rlbl = newiTempLabel(NULL);
3027
3028
3029     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3030     /* if caller saves & we have not saved then */
3031     if (!ic->regsSaved)
3032         saveRegisters(ic);
3033
3034     /* if we are calling a function that is not using
3035     the same register bank then we need to save the
3036     destination registers on the stack */
3037     dtype = operandType(IC_LEFT(ic));
3038     if (currFunc && dtype && 
3039         IFFUNC_ISISR(currFunc->type) &&
3040         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3041         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3042
3043
3044     /* push the return address on to the stack */
3045     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3046     pic16_emitcode("push","acc");    
3047     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3048     pic16_emitcode("push","acc");
3049     
3050     if (options.model == MODEL_FLAT24)
3051     {
3052         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3053         pic16_emitcode("push","acc");    
3054     }
3055
3056     /* now push the calling address */
3057     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3058
3059     pushSide(IC_LEFT(ic), FPTRSIZE);
3060
3061     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3062
3063     /* if send set is not empty the assign */
3064     if (_G.sendSet) {
3065         iCode *sic ;
3066
3067         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3068              sic = setNextItem(_G.sendSet)) {
3069             int size, offset = 0;
3070             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3071             size = AOP_SIZE(IC_LEFT(sic));
3072             while (size--) {
3073                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3074                                 FALSE,FALSE);
3075                 if (strcmp(l,fReturn[offset]))
3076                     pic16_emitcode("mov","%s,%s",
3077                              fReturn[offset],
3078                              l);
3079                 offset++;
3080             }
3081             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3082         }
3083         _G.sendSet = NULL;
3084     }
3085
3086     pic16_emitcode("ret","");
3087     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3088
3089
3090     /* if we need assign a result value */
3091     if ((IS_ITEMP(IC_RESULT(ic)) &&
3092          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3093           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3094         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3095
3096         _G.accInUse++;
3097         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3098         _G.accInUse--;
3099         
3100         assignResultValue(IC_RESULT(ic), 1);
3101
3102         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3103     }
3104
3105     /* adjust the stack for parameters if 
3106     required */
3107     if (ic->parmBytes) {
3108         int i;
3109         if (ic->parmBytes > 3) {
3110             pic16_emitcode("mov","a,%s",spname);
3111             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3112             pic16_emitcode("mov","%s,a",spname);
3113         } else 
3114             for ( i = 0 ; i <  ic->parmBytes ;i++)
3115                 pic16_emitcode("dec","%s",spname);
3116
3117     }
3118
3119     /* if register bank was saved then unsave them */
3120     if (currFunc && dtype && 
3121         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3122         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3123
3124     /* if we hade saved some registers then
3125     unsave them */
3126     if (ic->regsSaved)
3127         unsaveRegisters (ic);
3128
3129 }
3130 #endif                                                                          // patch 14
3131
3132
3133 /*-----------------------------------------------------------------*/
3134 /* resultRemat - result  is rematerializable                       */
3135 /*-----------------------------------------------------------------*/
3136 static int resultRemat (iCode *ic)
3137 {
3138   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3139   if (SKIP_IC(ic) || ic->op == IFX)
3140     return 0;
3141
3142   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3143     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3144     if (sym->remat && !POINTER_SET(ic)) 
3145       return 1;
3146   }
3147
3148   return 0;
3149 }
3150
3151 #if defined(__BORLANDC__) || defined(_MSC_VER)
3152 #define STRCASECMP stricmp
3153 #else
3154 #define STRCASECMP strcasecmp
3155 #endif
3156
3157 #if 0
3158 /*-----------------------------------------------------------------*/
3159 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3160 /*-----------------------------------------------------------------*/
3161 static bool inExcludeList(char *s)
3162 {
3163   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3164     int i =0;
3165     
3166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3167     if (options.excludeRegs[i] &&
3168     STRCASECMP(options.excludeRegs[i],"none") == 0)
3169         return FALSE ;
3170
3171     for ( i = 0 ; options.excludeRegs[i]; i++) {
3172         if (options.excludeRegs[i] &&
3173         STRCASECMP(s,options.excludeRegs[i]) == 0)
3174             return TRUE;
3175     }
3176     return FALSE ;
3177 }
3178 #endif
3179
3180 /*-----------------------------------------------------------------*/
3181 /* genFunction - generated code for function entry                 */
3182 /*-----------------------------------------------------------------*/
3183 static void genFunction (iCode *ic)
3184 {
3185   symbol *sym;
3186   sym_link *ftype;
3187   
3188         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3189
3190         labelOffset += (max_key+4);
3191         max_key=0;
3192         GpsuedoStkPtr=0;
3193         _G.nRegsSaved = 0;
3194
3195         ftype = operandType(IC_LEFT(ic));
3196         sym = OP_SYMBOL(IC_LEFT(ic));
3197
3198         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3199                 /* create an absolute section at the interrupt vector:
3200                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3201           symbol *asym;
3202           char asymname[128];
3203           pBlock *apb;
3204
3205                 {
3206                   int i, found=-1;
3207
3208                         sym = OP_SYMBOL( IC_LEFT(ic));
3209                         for(i=0;i<=2;i++) {
3210                                 if(interrupts[i]->name
3211                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3212                                         found = i;
3213                                         break;
3214                                 }
3215                         }
3216                         
3217                         if(found == -1) {
3218                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3219                                         __FILE__, __LINE__, sym->name);
3220                                 assert( 0 );
3221                         }
3222                         _G.interruptvector = found;
3223                 }
3224
3225                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3226                 asym = newSymbol(asymname, 0);
3227
3228                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3229                 pic16_addpBlock( apb );
3230
3231                 pic16_addpCode2pBlock(apb,
3232                         pic16_newpCodeCharP(";-----------------------------------------"));
3233
3234
3235                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3236
3237                 pic16_addpCode2pBlock(apb,
3238                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3239                 
3240                 /* mark the end of this tiny function */
3241                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3242
3243                 {
3244                   absSym *abSym;
3245
3246                         abSym = Safe_calloc(1, sizeof(absSym));
3247                         abSym->name = Safe_strdup( asymname );
3248
3249                         switch( _G.interruptvector ) {
3250                                 case 0: abSym->address = 0x000000; break;
3251                                 case 1: abSym->address = 0x000008; break;
3252                                 case 2: abSym->address = 0x000018; break;
3253                         }
3254
3255                         addSet(&absSymSet, abSym);
3256                 }
3257         }
3258
3259
3260         /* create the function header */
3261         pic16_emitcode(";","-----------------------------------------");
3262         pic16_emitcode(";"," function %s",sym->name);
3263         pic16_emitcode(";","-----------------------------------------");
3264
3265         pic16_emitcode("","%s:",sym->rname);
3266         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3267
3268
3269         {
3270           absSym *ab;
3271
3272                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3273                         if(!strcmp(ab->name, sym->name)) {
3274                                 pic16_pBlockConvert2Absolute(pb);
3275                                 break;
3276                         }
3277
3278         }
3279
3280
3281         if(IFFUNC_ISNAKED(ftype)) {
3282                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3283                 return;
3284         }
3285         
3286         /* if critical function then turn interrupts off */
3287         if (IFFUNC_ISCRITICAL(ftype))
3288                 pic16_emitcode("clr","ea");
3289
3290         /* if this is an interrupt service routine then
3291          * save acc, b, dpl, dph  */
3292         if (IFFUNC_ISISR(sym->type)) {
3293           int i;
3294                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3295                 if(!(_G.interruptvector == 1)) {
3296
3297                         /* do not save WREG,STATUS,BSR for high priority interrupts
3298                          * because they are stored in the hardware shadow registers already */
3299                          
3300                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3301                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3302                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3303                 }
3304
3305                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3306                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3307                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3308                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3309
3310 //                pic16_pBlockConvert2ISR(pb);
3311                 
3312                 /* if any registers used */
3313                 if (sym->regsUsed) {
3314                         /* save the registers used */
3315                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3316                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3317                                 if (bitVectBitValue(sym->regsUsed,i)) {
3318 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3319 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3320 //                                                      pic16_regWithIdx(i)->name);
3321
3322                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3323                                         _G.nRegsSaved++;
3324                                 }
3325                         }
3326                 }
3327         } else {
3328                 /* emit code to setup stack frame if user enabled,
3329                  * and function is not main() */
3330          
3331 //              fprintf(stderr, "function name: %s\n", sym->name);
3332                 if(strcmp(sym->name, "main")) {
3333                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3334                         /* setup the stack frame */
3335                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3336                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3337                                 if(STACK_MODEL_LARGE)
3338                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3339                         }
3340                 }
3341
3342                 /* if callee-save to be used for this function
3343                 * then save the registers being used in this function */
3344 //              if (IFFUNC_CALLEESAVES(sym->type))
3345                 {
3346                   int i;
3347
3348 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3349
3350 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3351
3352                         /* if any registers used */
3353                         if (sym->regsUsed) {
3354                                 /* save the registers used */
3355                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3356                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3357                                         if (bitVectBitValue(sym->regsUsed,i)) {
3358
3359 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3360 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3361 //                                                              pic16_regWithIdx(i)->name);
3362
3363                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3364
3365 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3366 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3367 //                                                      &pic16_pc_postdec1, 0));
3368
3369                                                 _G.nRegsSaved++;
3370                                         }
3371                                 }
3372                         }
3373                 }
3374         }
3375
3376
3377         
3378 #if 0
3379         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3380
3381                 if (options.useXstack) {
3382                         pic16_emitcode("mov","r0,%s",spname);
3383                         pic16_emitcode("mov","a,_bp");
3384                         pic16_emitcode("movx","@r0,a");
3385                         pic16_emitcode("inc","%s",spname);
3386                 } else {
3387                         /* set up the stack */
3388                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3389                 }
3390                 pic16_emitcode ("mov","_bp,%s",spname);
3391         }
3392 #endif
3393         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3394
3395         /* adjust the stack for the function */
3396         if (sym->stack) {
3397           int i = sym->stack;
3398
3399                 if (i > 127 ) 
3400                         werror(W_STACK_OVERFLOW,sym->name);
3401
3402                 if (i > 3 && sym->recvSize < 4) {              
3403                         pic16_emitcode ("mov","a,sp");
3404                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3405                         pic16_emitcode ("mov","sp,a");
3406                 } else
3407                         while(i--)
3408                                 pic16_emitcode("inc","sp");
3409         }
3410
3411         if (sym->xstack) {
3412                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3413
3414                 pic16_emitcode ("mov","a,_spx");
3415                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3416                 pic16_emitcode ("mov","_spx,a");
3417         }
3418     
3419 }
3420
3421 /*-----------------------------------------------------------------*/
3422 /* genEndFunction - generates epilogue for functions               */
3423 /*-----------------------------------------------------------------*/
3424 static void genEndFunction (iCode *ic)
3425 {
3426     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3427
3428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3429
3430     if(IFFUNC_ISNAKED(sym->type)) {
3431         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3432         return;
3433     }
3434
3435 #if 0
3436     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3437     {
3438         pic16_emitcode ("mov","%s,_bp",spname);
3439     }
3440 #endif
3441
3442     /* if use external stack but some variables were
3443     added to the local stack then decrement the
3444     local stack */
3445     if (options.useXstack && sym->stack) {      
3446         pic16_emitcode("mov","a,sp");
3447         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3448         pic16_emitcode("mov","sp,a");
3449     }
3450
3451
3452 #if 0
3453     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3454         if (options.useXstack) {
3455             pic16_emitcode("mov","r0,%s",spname);
3456             pic16_emitcode("movx","a,@r0");
3457             pic16_emitcode("mov","_bp,a");
3458             pic16_emitcode("dec","%s",spname);
3459         }
3460         else
3461         {
3462             pic16_emitcode ("pop","_bp");
3463         }
3464     }
3465 #endif
3466
3467         if (IFFUNC_ISISR(sym->type)) {
3468                 /* now we need to restore the registers */
3469                 /* if any registers used */
3470                 if (sym->regsUsed) {
3471                   int i;
3472
3473                         /* restore registers used */
3474                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3475                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3476                                 if (bitVectBitValue(sym->regsUsed,i)) {
3477
3478 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3479 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3480 //                                                      pic16_regWithIdx(i)->name);
3481
3482                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3483
3484 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3485 //                                                      &pic16_pc_preinc1,
3486 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3487
3488                                 }
3489                         }
3490                 }
3491         
3492                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3493                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3494                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3495                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3496
3497                 if(!(_G.interruptvector == 1)) {
3498                         /* do not restore interrupt vector for WREG,STATUS,BSR
3499                          * for high priority interrupt, see genFunction */
3500                          
3501                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3502                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3503                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3504                 }
3505         
3506                 _G.interruptvector = 0;         /* sanity check */
3507
3508 //              pic16_pBlockConvert2ISR(pb);
3509
3510
3511                 /* if debug then send end of function */
3512 /*      if (options.debug && currFunc)  */
3513                 if (currFunc) {
3514                         _G.debugLine = 1;
3515                         pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3516                                         FileBaseName(ic->filename),currFunc->lastLine,
3517                                         ic->level,ic->block); 
3518                         if (IS_STATIC(currFunc->etype))     
3519                                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3520                         else
3521                                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3522                         _G.debugLine = 0;
3523                 }
3524         
3525                 pic16_emitpcodeNULLop(POC_RETFIE);
3526         } else {
3527                 if (IFFUNC_ISCRITICAL(sym->type))
3528                         pic16_emitcode("setb","ea");
3529         
3530
3531 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3532
3533                 /* if any registers used */
3534                 if (sym->regsUsed) {
3535                   int i;
3536                         /* save the registers used */
3537                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3538                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3539                                 if (bitVectBitValue(sym->regsUsed,i)) {
3540         
3541 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3542 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3543 //                                                      pic16_regWithIdx(i)->name);
3544         
3545                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3546                                         
3547 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3548 //                                              &pic16_pc_preinc1,
3549 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3550
3551                                         _G.nRegsSaved--;
3552                                 }
3553                         }
3554                 }
3555         
3556                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3557                 /* if debug then send end of function */
3558                 if (currFunc) {
3559                     _G.debugLine = 1;
3560                     pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3561                              FileBaseName(ic->filename),currFunc->lastLine,
3562                              ic->level,ic->block); 
3563                     if (IS_STATIC(currFunc->etype))         
3564                         pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3565                     else
3566                         pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3567                     _G.debugLine = 0;
3568                 }
3569
3570                 /* insert code to restore stack frame, if user enabled it
3571                  * and function is not main() */
3572          
3573
3574                 if(strcmp(sym->name, "main")) {
3575                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3576                                 /* restore stack frame */
3577                                 if(STACK_MODEL_LARGE)
3578                                         pic16_emitpcode(POC_MOVFF,
3579                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3580                                 pic16_emitpcode(POC_MOVFF,
3581                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3582                         }
3583                 }
3584
3585                 pic16_emitcode ("return","");
3586                 pic16_emitpcodeNULLop(POC_RETURN);
3587
3588                 /* Mark the end of a function */
3589                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3590         }
3591
3592 }
3593
3594
3595 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3596 {
3597 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
3598
3599         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3600                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3601                 pic16_emitpcode(POC_MOVWF, dest);
3602         } else {
3603                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3604                         pic16_popGet(AOP(op), offset), dest));
3605         }
3606 }
3607
3608 /*-----------------------------------------------------------------*/
3609 /* genRet - generate code for return statement                     */
3610 /*-----------------------------------------------------------------*/
3611 static void genRet (iCode *ic)
3612 {
3613   int size;
3614   operand *left;
3615
3616         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3617         /* if we have no return value then
3618          * just generate the "ret" */
3619         
3620         if (!IC_LEFT(ic)) 
3621                 goto jumpret;       
3622     
3623         /* we have something to return then
3624          * move the return value into place */
3625         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3626         size = AOP_SIZE(IC_LEFT(ic));
3627
3628         if(size <= 4) {
3629                 if(size>3) {
3630                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3631 //                      pic16_emitpcode(POC_MOVFF,
3632 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3633                 }
3634                 if(size>2) {
3635                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3636 //                      pic16_emitpcode(POC_MOVFF,
3637 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3638                 }
3639                 if(size>1) {
3640                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3641 //                      pic16_emitpcode(POC_MOVFF,
3642 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3643                 }
3644
3645 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3646
3647                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3648 //              pic16_emitpcode(POC_MOVFF,
3649 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3650
3651         } else {
3652                 /* >32-bits, setup stack and FSR0 */
3653                 while (size--) {
3654 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3655 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3656
3657                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3658
3659 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3660                         GpsuedoStkPtr++;
3661                 }
3662                         
3663                 /* setup FSR0 */
3664                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3665                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3666
3667                 if(STACK_MODEL_LARGE) {
3668                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3669                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3670                 } else {
3671                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3672                 }
3673         }
3674                                 
3675 #if 0
3676         /* old code, left here for reference -- VR */    
3677         while (size--) {
3678           char *l ;
3679
3680                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3681                         /* #NOCHANGE */
3682                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3683                         pic16_emitpcomment("push %s",l);
3684                         pushed++;
3685                 } else {
3686                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3687                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3688                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3689                         
3690                         if (strcmp(fReturn[offset],l)) {
3691                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3692                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3693                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3694                                 } else {
3695                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3696                                 }
3697                                 
3698                                 if(size) {
3699                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3700                                 }
3701                                 offset++;
3702                         }
3703                 }
3704         }    
3705
3706         if (pushed) {
3707                 while(pushed) {
3708                         pushed--;
3709                         if (strcmp(fReturn[pushed],"a"))
3710                                 pic16_emitcode("pop",fReturn[pushed]);
3711                         else
3712                                 pic16_emitcode("pop","acc");
3713                 }
3714         }
3715 #endif
3716
3717
3718         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3719     
3720 jumpret:
3721         /* generate a jump to the return label
3722          * if the next is not the return statement */
3723         if (!(ic->next && ic->next->op == LABEL
3724                 && IC_LABEL(ic->next) == returnLabel)) {
3725         
3726                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3727                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3728         }
3729 }
3730
3731 /*-----------------------------------------------------------------*/
3732 /* genLabel - generates a label                                    */
3733 /*-----------------------------------------------------------------*/
3734 static void genLabel (iCode *ic)
3735 {
3736
3737
3738     /* special case never generate */
3739     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3740     if (IC_LABEL(ic) == entryLabel)
3741         return ;
3742
3743     pic16_emitpLabel(IC_LABEL(ic)->key);
3744     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3745 }
3746
3747 /*-----------------------------------------------------------------*/
3748 /* genGoto - generates a goto                                      */
3749 /*-----------------------------------------------------------------*/
3750 //tsd
3751 static void genGoto (iCode *ic)
3752 {
3753   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3754   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3755 }
3756
3757
3758 /*-----------------------------------------------------------------*/
3759 /* genMultbits :- multiplication of bits                           */
3760 /*-----------------------------------------------------------------*/
3761 static void genMultbits (operand *left, 
3762                          operand *right, 
3763                          operand *result)
3764 {
3765   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3766
3767   if(!pic16_sameRegs(AOP(result),AOP(right)))
3768     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3769
3770   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3771   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3772   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3773
3774 }
3775
3776
3777 /*-----------------------------------------------------------------*/
3778 /* genMultOneByte : 8 bit multiplication & division                */
3779 /*-----------------------------------------------------------------*/
3780 static void genMultOneByte (operand *left,
3781                             operand *right,
3782                             operand *result)
3783 {
3784
3785   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3786   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3787   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3788
3789   /* (if two literals, the value is computed before) */
3790   /* if one literal, literal on the right */
3791   if (AOP_TYPE(left) == AOP_LIT){
3792     operand *t = right;
3793     right = left;
3794     left = t;
3795   }
3796
3797         /* size is already checked in genMult == 1 */
3798 //      size = AOP_SIZE(result);
3799
3800         if (AOP_TYPE(right) == AOP_LIT){
3801                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3802                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3803                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3804                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3805         } else {
3806                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3807                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3808                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3809                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3810         }
3811         
3812         pic16_genMult8X8_8 (left, right,result);
3813
3814
3815 #if 0
3816     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3817                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3818                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3819                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3820
3821     if (SPEC_USIGN(opetype)){
3822       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3823       pic16_genUMult8X8_16 (left, right, result, NULL);
3824
3825       if (size > 2) {
3826         /* for filling the MSBs */
3827         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3828         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3829       }
3830     }
3831     else{
3832       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3833
3834       pic16_emitcode("mov","a,b");
3835
3836       /* adjust the MSB if left or right neg */
3837
3838       /* if one literal */
3839       if (AOP_TYPE(right) == AOP_LIT){
3840         pic16_emitcode("multiply ","right is a lit");
3841         /* AND literal negative */
3842         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3843           /* adjust MSB (c==0 after mul) */
3844           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3845         }
3846       }
3847       else{
3848         pic16_genSMult8X8_16 (left, right, result, NULL);
3849       }
3850
3851       if(size > 2){
3852         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3853         /* get the sign */
3854         pic16_emitcode("rlc","a");
3855         pic16_emitcode("subb","a,acc");
3856       }
3857     }
3858
3859     size -= 2;   
3860     offset = 2;
3861     if (size > 0)
3862       while (size--)
3863         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3864     //pic16_aopPut(AOP(result),"a",offset++);
3865   }
3866 #endif
3867
3868
3869 }
3870
3871 /*-----------------------------------------------------------------*/
3872 /* genMultOneWord : 16 bit multiplication                          */
3873 /*-----------------------------------------------------------------*/
3874 static void genMultOneWord (operand *left,
3875                             operand *right,
3876                             operand *result)
3877 {
3878
3879         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3880         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3881         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3882
3883         /* (if two literals, the value is computed before)
3884          * if one literal, literal on the right */
3885         if (AOP_TYPE(left) == AOP_LIT){
3886           operand *t = right;
3887                 right = left;
3888                 left = t;
3889         }
3890
3891         /* size is checked already == 2 */
3892 //      size = AOP_SIZE(result);
3893
3894         if (AOP_TYPE(right) == AOP_LIT) {
3895                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3896                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3897                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3898                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3899         } else {
3900                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3901                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3902                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3903                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3904         }
3905         
3906         pic16_genMult16X16_16(left, right,result);
3907 }
3908
3909 /*-----------------------------------------------------------------*/
3910 /* genMultOneLong : 32 bit multiplication                          */
3911 /*-----------------------------------------------------------------*/
3912 static void genMultOneLong (operand *left,
3913                             operand *right,
3914                             operand *result)
3915 {
3916
3917         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3918         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3919         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3920
3921         /* (if two literals, the value is computed before)
3922          * if one literal, literal on the right */
3923         if (AOP_TYPE(left) == AOP_LIT){
3924           operand *t = right;
3925                 right = left;
3926                 left = t;
3927         }
3928
3929         /* size is checked already == 4 */
3930 //      size = AOP_SIZE(result);
3931
3932         if (AOP_TYPE(right) == AOP_LIT) {
3933                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3934                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3935                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3936                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3937         } else {
3938                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3939                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3940                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3941                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3942         }
3943         
3944         pic16_genMult32X32_32(left, right,result);
3945 }
3946
3947
3948
3949 /*-----------------------------------------------------------------*/
3950 /* genMult - generates code for multiplication                     */
3951 /*-----------------------------------------------------------------*/
3952 static void genMult (iCode *ic)
3953 {
3954   operand *left = IC_LEFT(ic);
3955   operand *right = IC_RIGHT(ic);
3956   operand *result= IC_RESULT(ic);   
3957
3958         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3959         /* assign the amsops */
3960         pic16_aopOp (left,ic,FALSE);
3961         pic16_aopOp (right,ic,FALSE);
3962         pic16_aopOp (result,ic,TRUE);
3963
3964         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3965
3966         /* special cases first *
3967         * both are bits */
3968         if (AOP_TYPE(left) == AOP_CRY
3969                 && AOP_TYPE(right)== AOP_CRY) {
3970                 genMultbits(left,right,result);
3971           goto release ;
3972         }
3973
3974         /* if both are of size == 1 */
3975         if(AOP_SIZE(left) == 1
3976                 && AOP_SIZE(right) == 1) {
3977                 genMultOneByte(left,right,result);
3978           goto release ;
3979         }
3980
3981         /* if both are of size == 2 */
3982         if(AOP_SIZE(left) == 2
3983                 && AOP_SIZE(right) == 2) {
3984                 genMultOneWord(left, right, result);
3985           goto release;
3986         }
3987         
3988         /* if both are of size == 4 */
3989         if(AOP_SIZE(left) == 4
3990                 && AOP_SIZE(right) == 4) {
3991                 genMultOneLong(left, right, result);
3992           goto release;
3993         }
3994         
3995         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3996
3997
3998         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3999         /* should have been converted to function call */
4000         assert(0) ;
4001
4002 release :
4003         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4004         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4005         pic16_freeAsmop(result,NULL,ic,TRUE); 
4006 }
4007
4008 /*-----------------------------------------------------------------*/
4009 /* genDivbits :- division of bits                                  */
4010 /*-----------------------------------------------------------------*/
4011 static void genDivbits (operand *left, 
4012                         operand *right, 
4013                         operand *result)
4014 {
4015
4016     char *l;
4017
4018     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4019     /* the result must be bit */    
4020     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4021     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4022
4023     MOVA(l);    
4024
4025     pic16_emitcode("div","ab");
4026     pic16_emitcode("rrc","a");
4027     pic16_aopPut(AOP(result),"c",0);
4028 }
4029
4030 /*-----------------------------------------------------------------*/
4031 /* genDivOneByte : 8 bit division                                  */
4032 /*-----------------------------------------------------------------*/
4033 static void genDivOneByte (operand *left,
4034                            operand *right,
4035                            operand *result)
4036 {
4037     sym_link *opetype = operandType(result);
4038     char *l ;
4039     symbol *lbl ;
4040     int size,offset;
4041
4042     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4043     size = AOP_SIZE(result) - 1;
4044     offset = 1;
4045     /* signed or unsigned */
4046     if (SPEC_USIGN(opetype)) {
4047         /* unsigned is easy */
4048         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4049         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4050         MOVA(l);        
4051         pic16_emitcode("div","ab");
4052         pic16_aopPut(AOP(result),"a",0);
4053         while (size--)
4054             pic16_aopPut(AOP(result),zero,offset++);
4055         return ;
4056     }
4057
4058     /* signed is a little bit more difficult */
4059
4060     /* save the signs of the operands */
4061     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4062     MOVA(l);    
4063     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4064     pic16_emitcode("push","acc"); /* save it on the stack */
4065
4066     /* now sign adjust for both left & right */
4067     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4068     MOVA(l);       
4069     lbl = newiTempLabel(NULL);
4070     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4071     pic16_emitcode("cpl","a");   
4072     pic16_emitcode("inc","a");
4073     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4074     pic16_emitcode("mov","b,a");
4075
4076     /* sign adjust left side */
4077     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4078     MOVA(l);
4079
4080     lbl = newiTempLabel(NULL);
4081     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4082     pic16_emitcode("cpl","a");
4083     pic16_emitcode("inc","a");
4084     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4085
4086     /* now the division */
4087     pic16_emitcode("div","ab");
4088     /* we are interested in the lower order
4089     only */
4090     pic16_emitcode("mov","b,a");
4091     lbl = newiTempLabel(NULL);
4092     pic16_emitcode("pop","acc");   
4093     /* if there was an over flow we don't 
4094     adjust the sign of the result */
4095     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4096     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4097     CLRC;
4098     pic16_emitcode("clr","a");
4099     pic16_emitcode("subb","a,b");
4100     pic16_emitcode("mov","b,a");
4101     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4102
4103     /* now we are done */
4104     pic16_aopPut(AOP(result),"b",0);
4105     if(size > 0){
4106         pic16_emitcode("mov","c,b.7");
4107         pic16_emitcode("subb","a,acc");   
4108     }
4109     while (size--)
4110         pic16_aopPut(AOP(result),"a",offset++);
4111
4112 }
4113
4114 /*-----------------------------------------------------------------*/
4115 /* genDiv - generates code for division                            */
4116 /*-----------------------------------------------------------------*/
4117 static void genDiv (iCode *ic)
4118 {
4119     operand *left = IC_LEFT(ic);
4120     operand *right = IC_RIGHT(ic);
4121     operand *result= IC_RESULT(ic);   
4122
4123     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4124     /* assign the amsops */
4125     pic16_aopOp (left,ic,FALSE);
4126     pic16_aopOp (right,ic,FALSE);
4127     pic16_aopOp (result,ic,TRUE);
4128
4129     /* special cases first */
4130     /* both are bits */
4131     if (AOP_TYPE(left) == AOP_CRY &&
4132         AOP_TYPE(right)== AOP_CRY) {
4133         genDivbits(left,right,result);
4134         goto release ;
4135     }
4136
4137     /* if both are of size == 1 */
4138     if (AOP_SIZE(left) == 1 &&
4139         AOP_SIZE(right) == 1 ) {
4140         genDivOneByte(left,right,result);
4141         goto release ;
4142     }
4143
4144     /* should have been converted to function call */
4145     assert(0);
4146 release :
4147     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4148     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4149     pic16_freeAsmop(result,NULL,ic,TRUE); 
4150 }
4151
4152 /*-----------------------------------------------------------------*/
4153 /* genModbits :- modulus of bits                                   */
4154 /*-----------------------------------------------------------------*/
4155 static void genModbits (operand *left, 
4156                         operand *right, 
4157                         operand *result)
4158 {
4159
4160     char *l;
4161
4162     /* the result must be bit */    
4163     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4164     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4165
4166     MOVA(l);       
4167
4168     pic16_emitcode("div","ab");
4169     pic16_emitcode("mov","a,b");
4170     pic16_emitcode("rrc","a");
4171     pic16_aopPut(AOP(result),"c",0);
4172 }
4173
4174 /*-----------------------------------------------------------------*/
4175 /* genModOneByte : 8 bit modulus                                   */
4176 /*-----------------------------------------------------------------*/
4177 static void genModOneByte (operand *left,
4178                            operand *right,
4179                            operand *result)
4180 {
4181     sym_link *opetype = operandType(result);
4182     char *l ;
4183     symbol *lbl ;
4184
4185     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4186     /* signed or unsigned */
4187     if (SPEC_USIGN(opetype)) {
4188         /* unsigned is easy */
4189         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4190         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4191         MOVA(l);    
4192         pic16_emitcode("div","ab");
4193         pic16_aopPut(AOP(result),"b",0);
4194         return ;
4195     }
4196
4197     /* signed is a little bit more difficult */
4198
4199     /* save the signs of the operands */
4200     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4201     MOVA(l);
4202
4203     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4204     pic16_emitcode("push","acc"); /* save it on the stack */
4205
4206     /* now sign adjust for both left & right */
4207     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4208     MOVA(l);
4209
4210     lbl = newiTempLabel(NULL);
4211     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4212     pic16_emitcode("cpl","a");   
4213     pic16_emitcode("inc","a");
4214     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4215     pic16_emitcode("mov","b,a"); 
4216
4217     /* sign adjust left side */
4218     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4219     MOVA(l);
4220
4221     lbl = newiTempLabel(NULL);
4222     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4223     pic16_emitcode("cpl","a");   
4224     pic16_emitcode("inc","a");
4225     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4226
4227     /* now the multiplication */
4228     pic16_emitcode("div","ab");
4229     /* we are interested in the lower order
4230     only */
4231     lbl = newiTempLabel(NULL);
4232     pic16_emitcode("pop","acc");   
4233     /* if there was an over flow we don't 
4234     adjust the sign of the result */
4235     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4236     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4237     CLRC ;
4238     pic16_emitcode("clr","a");
4239     pic16_emitcode("subb","a,b");
4240     pic16_emitcode("mov","b,a");
4241     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4242
4243     /* now we are done */
4244     pic16_aopPut(AOP(result),"b",0);
4245
4246 }
4247
4248 /*-----------------------------------------------------------------*/
4249 /* genMod - generates code for division                            */
4250 /*-----------------------------------------------------------------*/
4251 static void genMod (iCode *ic)
4252 {
4253     operand *left = IC_LEFT(ic);
4254     operand *right = IC_RIGHT(ic);
4255     operand *result= IC_RESULT(ic);  
4256
4257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4258     /* assign the amsops */
4259     pic16_aopOp (left,ic,FALSE);
4260     pic16_aopOp (right,ic,FALSE);
4261     pic16_aopOp (result,ic,TRUE);
4262
4263     /* special cases first */
4264     /* both are bits */
4265     if (AOP_TYPE(left) == AOP_CRY &&
4266         AOP_TYPE(right)== AOP_CRY) {
4267         genModbits(left,right,result);
4268         goto release ;
4269     }
4270
4271     /* if both are of size == 1 */
4272     if (AOP_SIZE(left) == 1 &&
4273         AOP_SIZE(right) == 1 ) {
4274         genModOneByte(left,right,result);
4275         goto release ;
4276     }
4277
4278     /* should have been converted to function call */
4279     assert(0);
4280
4281 release :
4282     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4283     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4284     pic16_freeAsmop(result,NULL,ic,TRUE); 
4285 }
4286
4287 /*-----------------------------------------------------------------*/
4288 /* genIfxJump :- will create a jump depending on the ifx           */
4289 /*-----------------------------------------------------------------*/
4290 /*
4291   note: May need to add parameter to indicate when a variable is in bit space.
4292 */
4293 static void genIfxJump (iCode *ic, char *jval)
4294 {
4295
4296     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4297     /* if true label then we jump if condition
4298     supplied is true */
4299     if ( IC_TRUE(ic) ) {
4300
4301         if(strcmp(jval,"a") == 0)
4302           emitSKPZ;
4303         else if (strcmp(jval,"c") == 0)
4304           emitSKPC;
4305         else {
4306           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4307           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4308         }
4309
4310         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4311         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4312
4313     }
4314     else {
4315         /* false label is present */
4316         if(strcmp(jval,"a") == 0)
4317           emitSKPNZ;
4318         else if (strcmp(jval,"c") == 0)
4319           emitSKPNC;
4320         else {
4321           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4322           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4323         }
4324
4325         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4326         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4327
4328     }
4329
4330
4331     /* mark the icode as generated */
4332     ic->generated = 1;
4333 }
4334
4335 /*-----------------------------------------------------------------*/
4336 /* genSkip                                                         */
4337 /*-----------------------------------------------------------------*/
4338 static void genSkip(iCode *ifx,int status_bit)
4339 {
4340   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4341   if(!ifx)
4342     return;
4343
4344   if ( IC_TRUE(ifx) ) {
4345     switch(status_bit) {
4346     case 'z':
4347       emitSKPNZ;
4348       break;
4349
4350     case 'c':
4351       emitSKPNC;
4352       break;
4353
4354     case 'd':
4355       emitSKPDC;
4356       break;
4357
4358     }
4359
4360     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4361     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4362
4363   } else {
4364
4365     switch(status_bit) {
4366
4367     case 'z':
4368       emitSKPZ;
4369       break;
4370
4371     case 'c':
4372       emitSKPC;
4373       break;
4374
4375     case 'd':
4376       emitSKPDC;
4377       break;
4378     }
4379     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4380     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4381
4382   }
4383
4384 }
4385
4386 /*-----------------------------------------------------------------*/
4387 /* genSkipc                                                        */
4388 /*-----------------------------------------------------------------*/
4389 static void genSkipc(resolvedIfx *rifx)
4390 {
4391   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4392   
4393   if(!rifx)
4394     return;
4395
4396   if(rifx->condition)
4397     emitSKPC;
4398   else
4399     emitSKPNC;
4400
4401   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4402   rifx->generated = 1;
4403 }
4404
4405 /*-----------------------------------------------------------------*/
4406 /* genSkipz2                                                       */
4407 /*-----------------------------------------------------------------*/
4408 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4409 {
4410   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4411   
4412   if(!rifx)
4413     return;
4414
4415   if( (rifx->condition ^ invert_condition) & 1)
4416     emitSKPZ;
4417   else
4418     emitSKPNZ;
4419
4420   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4421   rifx->generated = 1;
4422 }
4423
4424 #if 0
4425 /*-----------------------------------------------------------------*/
4426 /* genSkipz                                                        */
4427 /*-----------------------------------------------------------------*/
4428 static void genSkipz(iCode *ifx, int condition)
4429 {
4430   if(!ifx)
4431     return;
4432
4433   if(condition)
4434     emitSKPNZ;
4435   else
4436     emitSKPZ;
4437
4438   if ( IC_TRUE(ifx) )
4439     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4440   else
4441     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4442
4443   if ( IC_TRUE(ifx) )
4444     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4445   else
4446     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4447
4448 }
4449 #endif
4450
4451 /*-----------------------------------------------------------------*/
4452 /* genSkipCond                                                     */
4453 /*-----------------------------------------------------------------*/
4454 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4455 {
4456   if(!rifx)
4457     return;
4458
4459   if(rifx->condition)
4460     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4461   else
4462     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4463
4464
4465   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4466   rifx->generated = 1;
4467 }
4468
4469 #if 0
4470 /*-----------------------------------------------------------------*/
4471 /* genChkZeroes :- greater or less than comparison                 */
4472 /*     For each byte in a literal that is zero, inclusive or the   */
4473 /*     the corresponding byte in the operand with W                */
4474 /*     returns true if any of the bytes are zero                   */
4475 /*-----------------------------------------------------------------*/
4476 static int genChkZeroes(operand *op, int lit,  int size)
4477 {
4478
4479   int i;
4480   int flag =1;
4481
4482   while(size--) {
4483     i = (lit >> (size*8)) & 0xff;
4484
4485     if(i==0) {
4486       if(flag) 
4487         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4488       else
4489         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4490       flag = 0;
4491     }
4492   }
4493
4494   return (flag==0);
4495 }
4496 #endif
4497
4498 /*-----------------------------------------------------------------*/
4499 /* genCmp :- greater or less than comparison                       */
4500 /*-----------------------------------------------------------------*/
4501 static void genCmp (operand *left,operand *right,
4502                     operand *result, iCode *ifx, int sign)
4503 {
4504   int size; //, offset = 0 ;
4505   unsigned long lit = 0L,i = 0;
4506   resolvedIfx rFalseIfx;
4507   //  resolvedIfx rTrueIfx;
4508   symbol *truelbl;
4509   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4510 /*
4511   if(ifx) {
4512     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4513     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4514   }
4515 */
4516
4517   resolveIfx(&rFalseIfx,ifx);
4518   truelbl  = newiTempLabel(NULL);
4519   size = max(AOP_SIZE(left),AOP_SIZE(right));
4520
4521   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4522
4523 #define _swapp
4524
4525   /* if literal is on the right then swap with left */
4526   if ((AOP_TYPE(right) == AOP_LIT)) {
4527     operand *tmp = right ;
4528     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4529     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4530 #ifdef _swapp
4531
4532     lit = (lit - 1) & mask;
4533     right = left;
4534     left = tmp;
4535     rFalseIfx.condition ^= 1;
4536 #endif
4537
4538   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4539     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4540   }
4541
4542
4543   //if(IC_TRUE(ifx) == NULL)
4544   /* if left & right are bit variables */
4545   if (AOP_TYPE(left) == AOP_CRY &&
4546       AOP_TYPE(right) == AOP_CRY ) {
4547     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4548     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4549   } else {
4550     /* subtract right from left if at the
4551        end the carry flag is set then we know that
4552        left is greater than right */
4553
4554     symbol *lbl  = newiTempLabel(NULL);
4555
4556 #if 0
4557         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4558                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4559 #endif
4560
4561 #ifndef _swapp
4562     if(AOP_TYPE(right) == AOP_LIT) {
4563
4564       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4565
4566       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4567
4568       /* special cases */
4569
4570       if(lit == 0) {
4571
4572         if(sign != 0) 
4573           genSkipCond(&rFalseIfx,left,size-1,7);
4574         else 
4575           /* no need to compare to 0...*/
4576           /* NOTE: this is a de-generate compare that most certainly 
4577            *       creates some dead code. */
4578           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4579
4580         if(ifx) ifx->generated = 1;
4581         return;
4582
4583       }
4584       size--;
4585
4586       if(size == 0) {
4587         //i = (lit >> (size*8)) & 0xff;
4588         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4589         
4590         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4591
4592         i = ((0-lit) & 0xff);
4593         if(sign) {
4594           if( i == 0x81) { 
4595             /* lit is 0x7f, all signed chars are less than
4596              * this except for 0x7f itself */
4597             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4598             genSkipz2(&rFalseIfx,0);
4599           } else {
4600             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4601             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4602             genSkipc(&rFalseIfx);
4603           }
4604
4605         } else {
4606           if(lit == 1) {
4607             genSkipz2(&rFalseIfx,1);
4608           } else {
4609             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4610             genSkipc(&rFalseIfx);
4611           }
4612         }
4613
4614         if(ifx) ifx->generated = 1;
4615         return;
4616       }
4617
4618       /* chars are out of the way. now do ints and longs */
4619
4620
4621       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4622         
4623       /* special cases */
4624
4625       if(sign) {
4626
4627         if(lit == 0) {
4628           genSkipCond(&rFalseIfx,left,size,7);
4629           if(ifx) ifx->generated = 1;
4630           return;
4631         }
4632
4633         if(lit <0x100) {
4634           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4635
4636           //rFalseIfx.condition ^= 1;
4637           //genSkipCond(&rFalseIfx,left,size,7);
4638           //rFalseIfx.condition ^= 1;
4639
4640           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4641           if(rFalseIfx.condition)
4642             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4643           else
4644             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4645
4646           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4647           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4648           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4649
4650           while(size > 1)
4651             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4652
4653           if(rFalseIfx.condition) {
4654             emitSKPZ;
4655             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4656
4657           } else {
4658             emitSKPNZ;
4659           }
4660
4661           genSkipc(&rFalseIfx);
4662           pic16_emitpLabel(truelbl->key);
4663           if(ifx) ifx->generated = 1;
4664           return;
4665
4666         }
4667
4668         if(size == 1) {
4669
4670           if( (lit & 0xff) == 0) {
4671             /* lower byte is zero */
4672             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4673             i = ((lit >> 8) & 0xff) ^0x80;
4674             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4675             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4676             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4677             genSkipc(&rFalseIfx);
4678
4679
4680             if(ifx) ifx->generated = 1;
4681             return;
4682
4683           }
4684         } else {
4685           /* Special cases for signed longs */
4686           if( (lit & 0xffffff) == 0) {
4687             /* lower byte is zero */
4688             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4689             i = ((lit >> 8*3) & 0xff) ^0x80;
4690             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4691             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4692             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4693             genSkipc(&rFalseIfx);
4694
4695
4696             if(ifx) ifx->generated = 1;
4697             return;
4698
4699           }
4700
4701         }
4702
4703
4704         if(lit & (0x80 << (size*8))) {
4705           /* lit is negative */
4706           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4707
4708           //genSkipCond(&rFalseIfx,left,size,7);
4709
4710           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4711
4712           if(rFalseIfx.condition)
4713             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4714           else
4715             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4716
4717
4718         } else {
4719           /* lit is positive */
4720           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4721           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4722           if(rFalseIfx.condition)
4723             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4724           else
4725             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4726
4727         }
4728
4729         /*
4730           This works, but is only good for ints.
4731           It also requires a "known zero" register.
4732           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4733           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4734           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4735           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4736           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4737           genSkipc(&rFalseIfx);
4738
4739           pic16_emitpLabel(truelbl->key);
4740           if(ifx) ifx->generated = 1;
4741           return;
4742         **/
4743           
4744         /* There are no more special cases, so perform a general compare */
4745   
4746         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4747         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4748
4749         while(size--) {
4750
4751           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4752           emitSKPNZ;
4753           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4754         }
4755         //rFalseIfx.condition ^= 1;
4756         genSkipc(&rFalseIfx);
4757
4758         pic16_emitpLabel(truelbl->key);
4759
4760         if(ifx) ifx->generated = 1;
4761         return;
4762
4763
4764       }
4765
4766
4767       /* sign is out of the way. So now do an unsigned compare */
4768       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4769
4770
4771       /* General case - compare to an unsigned literal on the right.*/
4772
4773       i = (lit >> (size*8)) & 0xff;
4774       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4775       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4776       while(size--) {
4777         i = (lit >> (size*8)) & 0xff;
4778
4779         if(i) {
4780           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4781           emitSKPNZ;
4782           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4783         } else {
4784           /* this byte of the lit is zero, 
4785            *if it's not the last then OR in the variable */
4786           if(size)
4787             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4788         }
4789       }
4790
4791
4792       pic16_emitpLabel(lbl->key);
4793 //      pic16_emitpLabel(truelbl->key);
4794       //if(emitFinalCheck)
4795       genSkipc(&rFalseIfx);
4796       if(sign)
4797         pic16_emitpLabel(truelbl->key);
4798
4799       if(ifx) ifx->generated = 1;
4800       return;
4801
4802
4803     }
4804 #endif  // _swapp
4805
4806     if(AOP_TYPE(left) == AOP_LIT) {
4807       //symbol *lbl = newiTempLabel(NULL);
4808
4809       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4810
4811
4812       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4813
4814       /* Special cases */
4815       if((lit == 0) && (sign == 0)){
4816
4817         size--;
4818         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4819         while(size) 
4820           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4821
4822         genSkipz2(&rFalseIfx,0);
4823         if(ifx) ifx->generated = 1;
4824         return;
4825       }
4826
4827       if(size==1) {
4828         /* Special cases */
4829         lit &= 0xff;
4830         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4831           /* degenerate compare can never be true */
4832           if(rFalseIfx.condition == 0)
4833             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4834
4835           if(ifx) ifx->generated = 1;
4836           return;
4837         }
4838
4839         if(sign) {
4840           /* signed comparisons to a literal byte */
4841
4842           int lp1 = (lit+1) & 0xff;
4843
4844           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4845           switch (lp1) {
4846           case 0:
4847             rFalseIfx.condition ^= 1;
4848             genSkipCond(&rFalseIfx,right,0,7);
4849             break;
4850           case 0x7f:
4851             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4852             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4853             genSkipz2(&rFalseIfx,1);
4854             break;
4855           default:
4856             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4857             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4858             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4859             rFalseIfx.condition ^= 1;
4860             genSkipc(&rFalseIfx);
4861             break;
4862           }
4863         } else {
4864           /* unsigned comparisons to a literal byte */
4865
4866           switch(lit & 0xff ) {
4867           case 0:
4868             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4869             genSkipz2(&rFalseIfx,0);
4870             break;
4871           case 0x7f:
4872             rFalseIfx.condition ^= 1;
4873             genSkipCond(&rFalseIfx,right,0,7);
4874             break;
4875
4876           default:
4877             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4878             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4879             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4880             rFalseIfx.condition ^= 1;
4881             if (AOP_TYPE(result) == AOP_CRY)
4882               genSkipc(&rFalseIfx);
4883             else {
4884               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4885               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4886             }         
4887             break;
4888           }
4889         }
4890
4891         if(ifx) ifx->generated = 1;
4892         //goto check_carry;
4893         return;
4894
4895       } else {
4896
4897         /* Size is greater than 1 */
4898
4899         if(sign) {
4900           int lp1 = lit+1;
4901
4902           size--;
4903
4904           if(lp1 == 0) {
4905             /* this means lit = 0xffffffff, or -1 */
4906
4907
4908             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4909             rFalseIfx.condition ^= 1;
4910             genSkipCond(&rFalseIfx,right,size,7);
4911             if(ifx) ifx->generated = 1;
4912             return;
4913           }
4914
4915           if(lit == 0) {
4916             int s = size;
4917
4918             if(rFalseIfx.condition) {
4919               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4920               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4921             }
4922
4923             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4924             while(size--)
4925               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4926
4927
4928             emitSKPZ;
4929             if(rFalseIfx.condition) {
4930               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4931               pic16_emitpLabel(truelbl->key);
4932             }else {
4933               rFalseIfx.condition ^= 1;
4934               genSkipCond(&rFalseIfx,right,s,7);
4935             }
4936
4937             if(ifx) ifx->generated = 1;
4938             return;
4939           }
4940
4941           if((size == 1) &&  (0 == (lp1&0xff))) {
4942             /* lower byte of signed word is zero */
4943             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4944             i = ((lp1 >> 8) & 0xff) ^0x80;
4945             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4946             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4947             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4948             rFalseIfx.condition ^= 1;
4949             genSkipc(&rFalseIfx);
4950
4951
4952             if(ifx) ifx->generated = 1;
4953             return;
4954           }
4955
4956           if(lit & (0x80 << (size*8))) {
4957             /* Lit is less than zero */
4958             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4959             //rFalseIfx.condition ^= 1;
4960             //genSkipCond(&rFalseIfx,left,size,7);
4961             //rFalseIfx.condition ^= 1;
4962             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4963             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4964
4965             if(rFalseIfx.condition)
4966               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4967             else
4968               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4969
4970
4971           } else {
4972             /* Lit is greater than or equal to zero */
4973             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4974             //rFalseIfx.condition ^= 1;
4975             //genSkipCond(&rFalseIfx,right,size,7);
4976             //rFalseIfx.condition ^= 1;
4977
4978             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4979             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4980
4981             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4982             if(rFalseIfx.condition)
4983               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4984             else
4985               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4986
4987           }
4988
4989
4990           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4991           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4992
4993           while(size--) {
4994
4995             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4996             emitSKPNZ;
4997             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4998           }
4999           rFalseIfx.condition ^= 1;
5000           //rFalseIfx.condition = 1;
5001           genSkipc(&rFalseIfx);
5002
5003           pic16_emitpLabel(truelbl->key);
5004
5005           if(ifx) ifx->generated = 1;
5006           return;
5007           // end of if (sign)
5008         } else {
5009
5010           /* compare word or long to an unsigned literal on the right.*/
5011
5012
5013           size--;
5014           if(lit < 0xff) {
5015             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5016             switch (lit) {
5017             case 0:
5018               break; /* handled above */
5019 /*
5020             case 0xff:
5021               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5022               while(size--)
5023                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5024               genSkipz2(&rFalseIfx,0);
5025               break;
5026 */
5027             default:
5028               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5029               while(--size)
5030                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5031
5032               emitSKPZ;
5033               if(rFalseIfx.condition)
5034                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5035               else
5036                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5037
5038
5039               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5040               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5041
5042               rFalseIfx.condition ^= 1;
5043               genSkipc(&rFalseIfx);
5044             }
5045
5046             pic16_emitpLabel(truelbl->key);
5047
5048             if(ifx) ifx->generated = 1;
5049             return;
5050           }
5051
5052
5053           lit++;
5054           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5055           i = (lit >> (size*8)) & 0xff;
5056
5057           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5058           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5059
5060           while(size--) {
5061             i = (lit >> (size*8)) & 0xff;
5062
5063             if(i) {
5064               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5065               emitSKPNZ;
5066               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5067             } else {
5068               /* this byte of the lit is zero, 
5069                * if it's not the last then OR in the variable */
5070               if(size)
5071                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5072             }
5073           }
5074
5075
5076           pic16_emitpLabel(lbl->key);
5077
5078           rFalseIfx.condition ^= 1;
5079
5080           genSkipc(&rFalseIfx);
5081         }
5082
5083         if(sign)
5084           pic16_emitpLabel(truelbl->key);
5085         if(ifx) ifx->generated = 1;
5086         return;
5087       }
5088     }
5089     /* Compare two variables */
5090
5091     DEBUGpic16_emitcode(";sign","%d",sign);
5092
5093     size--;
5094     if(sign) {
5095       /* Sigh. thus sucks... */
5096       if(size) {
5097         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5098         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5099         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5100         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5101         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5102         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5103       } else {
5104         /* Signed char comparison */
5105         /* Special thanks to Nikolai Golovchenko for this snippet */
5106         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5107         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5108         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5109         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5110         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5111         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5112
5113         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5114         genSkipc(&rFalseIfx);
5115           
5116         if(ifx) ifx->generated = 1;
5117         return;
5118       }
5119
5120     } else {
5121
5122       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5123       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5124     }
5125
5126
5127     /* The rest of the bytes of a multi-byte compare */
5128     while (size) {
5129
5130       emitSKPZ;
5131       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5132       size--;
5133
5134       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5135       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5136
5137
5138     }
5139
5140     pic16_emitpLabel(lbl->key);
5141
5142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5143     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5144         (AOP_TYPE(result) == AOP_REG)) {
5145       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5146       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5147     } else {
5148       genSkipc(&rFalseIfx);
5149     }         
5150     //genSkipc(&rFalseIfx);
5151     if(ifx) ifx->generated = 1;
5152
5153     return;
5154
5155   }
5156
5157   // check_carry:
5158   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5159     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5160     pic16_outBitC(result);
5161   } else {
5162     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5163     /* if the result is used in the next
5164        ifx conditional branch then generate
5165        code a little differently */
5166     if (ifx )
5167       genIfxJump (ifx,"c");
5168     else
5169       pic16_outBitC(result);
5170     /* leave the result in acc */
5171   }
5172
5173 }
5174
5175 /*-----------------------------------------------------------------*/
5176 /* genCmpGt :- greater than comparison                             */
5177 /*-----------------------------------------------------------------*/
5178 static void genCmpGt (iCode *ic, iCode *ifx)
5179 {
5180     operand *left, *right, *result;
5181     sym_link *letype , *retype;
5182     int sign ;
5183
5184     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5185     left = IC_LEFT(ic);
5186     right= IC_RIGHT(ic);
5187     result = IC_RESULT(ic);
5188
5189     letype = getSpec(operandType(left));
5190     retype =getSpec(operandType(right));
5191     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5192     /* assign the amsops */
5193     pic16_aopOp (left,ic,FALSE);
5194     pic16_aopOp (right,ic,FALSE);
5195     pic16_aopOp (result,ic,TRUE);
5196
5197     genCmp(right, left, result, ifx, sign);
5198
5199     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5200     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5201     pic16_freeAsmop(result,NULL,ic,TRUE); 
5202 }
5203
5204 /*-----------------------------------------------------------------*/
5205 /* genCmpLt - less than comparisons                                */
5206 /*-----------------------------------------------------------------*/
5207 static void genCmpLt (iCode *ic, iCode *ifx)
5208 {
5209     operand *left, *right, *result;
5210     sym_link *letype , *retype;
5211     int sign ;
5212
5213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5214     left = IC_LEFT(ic);
5215     right= IC_RIGHT(ic);
5216     result = IC_RESULT(ic);
5217
5218     letype = getSpec(operandType(left));
5219     retype =getSpec(operandType(right));
5220     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5221
5222     /* assign the amsops */
5223     pic16_aopOp (left,ic,FALSE);
5224     pic16_aopOp (right,ic,FALSE);
5225     pic16_aopOp (result,ic,TRUE);
5226
5227     genCmp(left, right, result, ifx, sign);
5228
5229     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5230     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5231     pic16_freeAsmop(result,NULL,ic,TRUE); 
5232 }
5233
5234 /*-----------------------------------------------------------------*/
5235 /* genc16bit2lit - compare a 16 bit value to a literal             */
5236 /*-----------------------------------------------------------------*/
5237 static void genc16bit2lit(operand *op, int lit, int offset)
5238 {
5239   int i;
5240
5241   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5242   if( (lit&0xff) == 0) 
5243     i=1;
5244   else
5245     i=0;
5246
5247   switch( BYTEofLONG(lit,i)) { 
5248   case 0:
5249     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5250     break;
5251   case 1:
5252     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5253     break;
5254   case 0xff:
5255     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5256     break;
5257   default:
5258     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5259     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5260   }
5261
5262   i ^= 1;
5263
5264   switch( BYTEofLONG(lit,i)) { 
5265   case 0:
5266     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5267     break;
5268   case 1:
5269     emitSKPNZ;
5270     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5271     break;
5272   case 0xff:
5273     emitSKPNZ;
5274     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5275     break;
5276   default:
5277     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5278     emitSKPNZ;
5279     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5280
5281   }
5282
5283 }
5284
5285 /*-----------------------------------------------------------------*/
5286 /* gencjneshort - compare and jump if not equal                    */
5287 /*-----------------------------------------------------------------*/
5288 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5289 {
5290   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5291   int offset = 0;
5292   int res_offset = 0;  /* the result may be a different size then left or right */
5293   int res_size = AOP_SIZE(result);
5294   resolvedIfx rIfx;
5295   symbol *lbl, *lbl_done;
5296
5297   unsigned long lit = 0L;
5298   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5299
5300   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5301   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5302   if(result)
5303     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5304   resolveIfx(&rIfx,ifx);
5305   lbl =  newiTempLabel(NULL);
5306   lbl_done =  newiTempLabel(NULL);
5307
5308
5309   /* if the left side is a literal or 
5310      if the right is in a pointer register and left 
5311      is not */
5312   if ((AOP_TYPE(left) == AOP_LIT) || 
5313       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5314     operand *t = right;
5315     right = left;
5316     left = t;
5317   }
5318   if(AOP_TYPE(right) == AOP_LIT)
5319     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5320
5321   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5322     preserve_result = 1;
5323
5324   if(result && !preserve_result)
5325     {
5326       int i;
5327       for(i = 0; i < AOP_SIZE(result); i++)
5328         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5329     }
5330
5331
5332   /* if the right side is a literal then anything goes */
5333   if (AOP_TYPE(right) == AOP_LIT &&
5334       AOP_TYPE(left) != AOP_DIR ) {
5335     switch(size) {
5336     case 2:
5337       genc16bit2lit(left, lit, 0);
5338       emitSKPZ;
5339       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5340       break;
5341     default:
5342       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5343       while (size--) {
5344         if(lit & 0xff) {
5345           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5346           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5347         } else {
5348           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5349         }
5350
5351         emitSKPZ;
5352         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5353         offset++;
5354         if(res_offset < res_size-1)
5355           res_offset++;
5356         lit >>= 8;
5357       }
5358       break;
5359     }
5360   }
5361
5362   /* if the right side is in a register or in direct space or
5363      if the left is a pointer register & right is not */    
5364   else if (AOP_TYPE(right) == AOP_REG ||
5365            AOP_TYPE(right) == AOP_DIR || 
5366            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5367            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5368     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5369     int lbl_key = lbl->key;
5370
5371     if(result) {
5372       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5373       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5374     }else {
5375       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5376       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5377               __FUNCTION__,__LINE__);
5378       return;
5379     }
5380    
5381 /*     switch(size) { */
5382 /*     case 2: */
5383 /*       genc16bit2lit(left, lit, 0); */
5384 /*       emitSKPNZ; */
5385 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5386 /*       break; */
5387 /*     default: */
5388     while (size--) {
5389       int emit_skip=1;
5390       if((AOP_TYPE(left) == AOP_DIR) && 
5391          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5392
5393         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5394         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5395
5396       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5397             
5398         switch (lit & 0xff) {
5399         case 0:
5400           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5401           break;
5402         case 1:
5403           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5404           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5405           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5406           emit_skip=0;
5407           break;
5408         case 0xff:
5409           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5410           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5411           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5412           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5413           emit_skip=0;
5414           break;
5415         default:
5416           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5417           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5418         }
5419         lit >>= 8;
5420
5421       } else {
5422         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5423       }
5424       if(emit_skip) {
5425         if(AOP_TYPE(result) == AOP_CRY) {
5426           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5427           if(rIfx.condition)
5428             emitSKPNZ;
5429           else
5430             emitSKPZ;
5431           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5432         } else {
5433           /* fix me. probably need to check result size too */
5434           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5435           if(rIfx.condition)
5436             emitSKPZ;
5437           else
5438             emitSKPNZ;
5439           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5440           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5441         }
5442         if(ifx)
5443           ifx->generated=1;
5444       }
5445       emit_skip++;
5446       offset++;
5447       if(res_offset < res_size-1)
5448         res_offset++;
5449     }
5450 /*       break; */
5451 /*     } */
5452   } else if(AOP_TYPE(right) == AOP_REG &&
5453             AOP_TYPE(left) != AOP_DIR){
5454
5455     while(size--) {
5456       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5457       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5458       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5459       if(rIfx.condition)
5460         emitSKPNZ;
5461       else
5462         emitSKPZ;
5463       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5464       offset++;
5465       if(res_offset < res_size-1)
5466         res_offset++;
5467     }
5468       
5469   }else{
5470     /* right is a pointer reg need both a & b */
5471     while(size--) {
5472       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5473       if(strcmp(l,"b"))
5474         pic16_emitcode("mov","b,%s",l);
5475       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5476       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5477       offset++;
5478     }
5479   }
5480
5481   if(result && preserve_result)
5482     {
5483       int i;
5484       for(i = 0; i < AOP_SIZE(result); i++)
5485         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5486     }
5487
5488   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5489
5490   if(result && preserve_result)
5491     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5492
5493   if(!rIfx.condition)
5494     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5495
5496   pic16_emitpLabel(lbl->key);
5497
5498   if(result && preserve_result)
5499     {
5500       int i;
5501       for(i = 0; i < AOP_SIZE(result); i++)
5502         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5503
5504       pic16_emitpLabel(lbl_done->key);
5505    }
5506
5507   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5508
5509   if(ifx)
5510     ifx->generated = 1;
5511 }
5512
5513 #if 0
5514 /*-----------------------------------------------------------------*/
5515 /* gencjne - compare and jump if not equal                         */
5516 /*-----------------------------------------------------------------*/
5517 static void gencjne(operand *left, operand *right, iCode *ifx)
5518 {
5519     symbol *tlbl  = newiTempLabel(NULL);
5520
5521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5522     gencjneshort(left, right, lbl);
5523
5524     pic16_emitcode("mov","a,%s",one);
5525     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5526     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5527     pic16_emitcode("clr","a");
5528     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5529
5530     pic16_emitpLabel(lbl->key);
5531     pic16_emitpLabel(tlbl->key);
5532
5533 }
5534 #endif
5535
5536 /*-----------------------------------------------------------------*/
5537 /* genCmpEq - generates code for equal to                          */
5538 /*-----------------------------------------------------------------*/
5539 static void genCmpEq (iCode *ic, iCode *ifx)
5540 {
5541     operand *left, *right, *result;
5542     unsigned long lit = 0L;
5543     int size,offset=0;
5544     symbol *falselbl  = newiTempLabel(NULL);
5545
5546
5547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5548
5549     if(ifx)
5550       DEBUGpic16_emitcode ("; ifx is non-null","");
5551     else
5552       DEBUGpic16_emitcode ("; ifx is null","");
5553
5554     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5555     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5556     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5557
5558     size = max(AOP_SIZE(left),AOP_SIZE(right));
5559
5560     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5561
5562     /* if literal, literal on the right or 
5563     if the right is in a pointer register and left 
5564     is not */
5565     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5566         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5567       operand *tmp = right ;
5568       right = left;
5569       left = tmp;
5570     }
5571
5572
5573     if(ifx && !AOP_SIZE(result)){
5574         symbol *tlbl;
5575         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5576         /* if they are both bit variables */
5577         if (AOP_TYPE(left) == AOP_CRY &&
5578             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5579                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5580             if(AOP_TYPE(right) == AOP_LIT){
5581                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5582                 if(lit == 0L){
5583                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5584                     pic16_emitcode("cpl","c");
5585                 } else if(lit == 1L) {
5586                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5587                 } else {
5588                     pic16_emitcode("clr","c");
5589                 }
5590                 /* AOP_TYPE(right) == AOP_CRY */
5591             } else {
5592                 symbol *lbl = newiTempLabel(NULL);
5593                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5594                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5595                 pic16_emitcode("cpl","c");
5596                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5597             }
5598             /* if true label then we jump if condition
5599             supplied is true */
5600             tlbl = newiTempLabel(NULL);
5601             if ( IC_TRUE(ifx) ) {
5602                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5603                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5604             } else {
5605                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5606                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5607             }
5608             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5609
5610                 {
5611                 /* left and right are both bit variables, result is carry */
5612                         resolvedIfx rIfx;
5613               
5614                         resolveIfx(&rIfx,ifx);
5615
5616                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5617                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5618                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5619                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5620                         genSkipz2(&rIfx,0);
5621                 }
5622         } else {
5623
5624                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5625
5626                         /* They're not both bit variables. Is the right a literal? */
5627                         if(AOP_TYPE(right) == AOP_LIT) {
5628                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5629             
5630                         switch(size) {
5631
5632                                 case 1:
5633                                         switch(lit & 0xff) {
5634                                                 case 1:
5635                                                                 if ( IC_TRUE(ifx) ) {
5636                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5637                                                                         emitSKPNZ;
5638                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5639                                                                 } else {
5640                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5641                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5642                                                                 }
5643                                                                 break;
5644                                                 case 0xff:
5645                                                                 if ( IC_TRUE(ifx) ) {
5646                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5647                                                                         emitSKPNZ;
5648                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5649                                                                 } else {
5650                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5651                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5652                                                                 }
5653                                                                 break;
5654                                                 default:
5655                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5656                                                                 if(lit)
5657                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5658                                                                 genSkip(ifx,'z');
5659                                         } // switch lit
5660
5661
5662                                         /* end of size == 1 */
5663                                         break;
5664               
5665                                 case 2:
5666                                         genc16bit2lit(left,lit,offset);
5667                                         genSkip(ifx,'z');
5668                                         break;
5669                                         /* end of size == 2 */
5670
5671                                 default:
5672                                         /* size is 4 */
5673                                         if(lit==0) {
5674                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5675                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5676                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5677                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5678                                                 genSkip(ifx,'z');
5679                                         } else {
5680                                                 /* search for patterns that can be optimized */
5681
5682                                                 genc16bit2lit(left,lit,0);
5683                                                 lit >>= 16;
5684                                                 if(lit) {
5685                                                                 if(IC_TRUE(ifx))
5686                                                                 emitSKPZ; // if hi word unequal
5687                                                                 else
5688                                                                 emitSKPNZ; // if hi word equal
5689                                                                 // fail early
5690                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5691                                                         genc16bit2lit(left,lit,2);
5692                                                         genSkip(ifx,'z');
5693                                                 } else {
5694                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5695                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5696                                                         genSkip(ifx,'z');
5697                                                 }
5698                                         }
5699                                                 pic16_emitpLabel(falselbl->key);
5700                                                 break;
5701
5702                         } // switch size
5703           
5704                         ifx->generated = 1;
5705                         goto release ;
5706             
5707
5708           } else if(AOP_TYPE(right) == AOP_CRY ) {
5709             /* we know the left is not a bit, but that the right is */
5710             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5711             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5712                       pic16_popGet(AOP(right),offset));
5713             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5714
5715             /* if the two are equal, then W will be 0 and the Z bit is set
5716              * we could test Z now, or go ahead and check the high order bytes if
5717              * the variable we're comparing is larger than a byte. */
5718
5719             while(--size)
5720               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5721
5722             if ( IC_TRUE(ifx) ) {
5723               emitSKPNZ;
5724               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5725               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5726             } else {
5727               emitSKPZ;
5728               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5729               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5730             }
5731
5732           } else {
5733             /* They're both variables that are larger than bits */
5734             int s = size;
5735
5736             tlbl = newiTempLabel(NULL);
5737
5738             while(size--) {
5739               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5740               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5741
5742               if ( IC_TRUE(ifx) ) {
5743                 if(size) {
5744                   emitSKPZ;
5745                 
5746                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5747
5748                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5749                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5750                 } else {
5751                   emitSKPNZ;
5752
5753                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5754
5755
5756                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5757                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5758                 }
5759               } else {
5760                 emitSKPZ;
5761
5762                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5763
5764                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5765                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5766               }
5767               offset++;
5768             }
5769             if(s>1 && IC_TRUE(ifx)) {
5770               pic16_emitpLabel(tlbl->key);
5771               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5772             }
5773           }
5774         }
5775         /* mark the icode as generated */
5776         ifx->generated = 1;
5777         goto release ;
5778     }
5779
5780     /* if they are both bit variables */
5781     if (AOP_TYPE(left) == AOP_CRY &&
5782         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5783         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5784         if(AOP_TYPE(right) == AOP_LIT){
5785             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5786             if(lit == 0L){
5787                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5788                 pic16_emitcode("cpl","c");
5789             } else if(lit == 1L) {
5790                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5791             } else {
5792                 pic16_emitcode("clr","c");
5793             }
5794             /* AOP_TYPE(right) == AOP_CRY */
5795         } else {
5796             symbol *lbl = newiTempLabel(NULL);
5797             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5798             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5799             pic16_emitcode("cpl","c");
5800             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5801         }
5802         /* c = 1 if egal */
5803         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5804             pic16_outBitC(result);
5805             goto release ;
5806         }
5807         if (ifx) {
5808             genIfxJump (ifx,"c");
5809             goto release ;
5810         }
5811         /* if the result is used in an arithmetic operation
5812         then put the result in place */
5813         pic16_outBitC(result);
5814     } else {
5815       
5816       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5817       gencjne(left,right,result,ifx);
5818 /*
5819       if(ifx) 
5820         gencjne(left,right,newiTempLabel(NULL));
5821       else {
5822         if(IC_TRUE(ifx)->key)
5823           gencjne(left,right,IC_TRUE(ifx)->key);
5824         else
5825           gencjne(left,right,IC_FALSE(ifx)->key);
5826         ifx->generated = 1;
5827         goto release ;
5828       }
5829       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5830         pic16_aopPut(AOP(result),"a",0);
5831         goto release ;
5832       }
5833
5834       if (ifx) {
5835         genIfxJump (ifx,"a");
5836         goto release ;
5837       }
5838 */
5839       /* if the result is used in an arithmetic operation
5840          then put the result in place */
5841 /*
5842       if (AOP_TYPE(result) != AOP_CRY) 
5843         pic16_outAcc(result);
5844 */
5845       /* leave the result in acc */
5846     }
5847
5848 release:
5849     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5850     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5851     pic16_freeAsmop(result,NULL,ic,TRUE);
5852 }
5853
5854 /*-----------------------------------------------------------------*/
5855 /* ifxForOp - returns the icode containing the ifx for operand     */
5856 /*-----------------------------------------------------------------*/
5857 static iCode *ifxForOp ( operand *op, iCode *ic )
5858 {
5859     /* if true symbol then needs to be assigned */
5860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5861     if (IS_TRUE_SYMOP(op))
5862         return NULL ;
5863
5864     /* if this has register type condition and
5865     the next instruction is ifx with the same operand
5866     and live to of the operand is upto the ifx only then */
5867     if (ic->next &&
5868         ic->next->op == IFX &&
5869         IC_COND(ic->next)->key == op->key &&
5870         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5871         return ic->next;
5872
5873     if (ic->next &&
5874         ic->next->op == IFX &&
5875         IC_COND(ic->next)->key == op->key) {
5876       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5877       return ic->next;
5878     }
5879
5880     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5881     if (ic->next &&
5882         ic->next->op == IFX)
5883       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5884
5885     if (ic->next &&
5886         ic->next->op == IFX &&
5887         IC_COND(ic->next)->key == op->key) {
5888       DEBUGpic16_emitcode ("; "," key is okay");
5889       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5890                            OP_SYMBOL(op)->liveTo,
5891                            ic->next->seq);
5892     }
5893
5894
5895 #if 0
5896     /* the code below is completely untested
5897      * it just allows ulong2fs.c compile -- VR */
5898          
5899     ic = ic->next;
5900     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5901                                         __FILE__, __FUNCTION__, __LINE__);
5902         
5903     /* if this has register type condition and
5904     the next instruction is ifx with the same operand
5905     and live to of the operand is upto the ifx only then */
5906     if (ic->next &&
5907         ic->next->op == IFX &&
5908         IC_COND(ic->next)->key == op->key &&
5909         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5910         return ic->next;
5911
5912     if (ic->next &&
5913         ic->next->op == IFX &&
5914         IC_COND(ic->next)->key == op->key) {
5915       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5916       return ic->next;
5917     }
5918
5919     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5920                                         __FILE__, __FUNCTION__, __LINE__);
5921
5922 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5923 #endif
5924     return NULL;
5925 }
5926 /*-----------------------------------------------------------------*/
5927 /* genAndOp - for && operation                                     */
5928 /*-----------------------------------------------------------------*/
5929 static void genAndOp (iCode *ic)
5930 {
5931     operand *left,*right, *result;
5932 /*     symbol *tlbl; */
5933
5934     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5935     /* note here that && operations that are in an
5936     if statement are taken away by backPatchLabels
5937     only those used in arthmetic operations remain */
5938     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5939     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5940     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5941
5942     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5943
5944     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5945     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5946     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5947
5948     /* if both are bit variables */
5949 /*     if (AOP_TYPE(left) == AOP_CRY && */
5950 /*         AOP_TYPE(right) == AOP_CRY ) { */
5951 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5952 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5953 /*         pic16_outBitC(result); */
5954 /*     } else { */
5955 /*         tlbl = newiTempLabel(NULL); */
5956 /*         pic16_toBoolean(left);     */
5957 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5958 /*         pic16_toBoolean(right); */
5959 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5960 /*         pic16_outBitAcc(result); */
5961 /*     } */
5962
5963     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5964     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5965     pic16_freeAsmop(result,NULL,ic,TRUE);
5966 }
5967
5968
5969 /*-----------------------------------------------------------------*/
5970 /* genOrOp - for || operation                                      */
5971 /*-----------------------------------------------------------------*/
5972 /*
5973   tsd pic port -
5974   modified this code, but it doesn't appear to ever get called
5975 */
5976
5977 static void genOrOp (iCode *ic)
5978 {
5979     operand *left,*right, *result;
5980     symbol *tlbl;
5981
5982     /* note here that || operations that are in an
5983     if statement are taken away by backPatchLabels
5984     only those used in arthmetic operations remain */
5985     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5986     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5987     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5988     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5989
5990     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5991
5992     /* if both are bit variables */
5993     if (AOP_TYPE(left) == AOP_CRY &&
5994         AOP_TYPE(right) == AOP_CRY ) {
5995       pic16_emitcode("clrc","");
5996       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5997                AOP(left)->aopu.aop_dir,
5998                AOP(left)->aopu.aop_dir);
5999       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6000                AOP(right)->aopu.aop_dir,
6001                AOP(right)->aopu.aop_dir);
6002       pic16_emitcode("setc","");
6003
6004     } else {
6005         tlbl = newiTempLabel(NULL);
6006         pic16_toBoolean(left);
6007         emitSKPZ;
6008         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6009         pic16_toBoolean(right);
6010         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6011
6012         pic16_outBitAcc(result);
6013     }
6014
6015     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6016     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6017     pic16_freeAsmop(result,NULL,ic,TRUE);            
6018 }
6019
6020 /*-----------------------------------------------------------------*/
6021 /* isLiteralBit - test if lit == 2^n                               */
6022 /*-----------------------------------------------------------------*/
6023 static int isLiteralBit(unsigned long lit)
6024 {
6025     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6026     0x100L,0x200L,0x400L,0x800L,
6027     0x1000L,0x2000L,0x4000L,0x8000L,
6028     0x10000L,0x20000L,0x40000L,0x80000L,
6029     0x100000L,0x200000L,0x400000L,0x800000L,
6030     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6031     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6032     int idx;
6033     
6034     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6035     for(idx = 0; idx < 32; idx++)
6036         if(lit == pw[idx])
6037             return idx+1;
6038     return 0;
6039 }
6040
6041 /*-----------------------------------------------------------------*/
6042 /* continueIfTrue -                                                */
6043 /*-----------------------------------------------------------------*/
6044 static void continueIfTrue (iCode *ic)
6045 {
6046     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6047     if(IC_TRUE(ic))
6048         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6049     ic->generated = 1;
6050 }
6051
6052 /*-----------------------------------------------------------------*/
6053 /* jmpIfTrue -                                                     */
6054 /*-----------------------------------------------------------------*/
6055 static void jumpIfTrue (iCode *ic)
6056 {
6057     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6058     if(!IC_TRUE(ic))
6059         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6060     ic->generated = 1;
6061 }
6062
6063 /*-----------------------------------------------------------------*/
6064 /* jmpTrueOrFalse -                                                */
6065 /*-----------------------------------------------------------------*/
6066 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6067 {
6068     // ugly but optimized by peephole
6069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6070     if(IC_TRUE(ic)){
6071         symbol *nlbl = newiTempLabel(NULL);
6072         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6073         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6074         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6075         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6076     }
6077     else{
6078         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6079         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6080     }
6081     ic->generated = 1;
6082 }
6083
6084 /*-----------------------------------------------------------------*/
6085 /* genAnd  - code for and                                          */
6086 /*-----------------------------------------------------------------*/
6087 static void genAnd (iCode *ic, iCode *ifx)
6088 {
6089   operand *left, *right, *result;
6090   int size, offset=0;  
6091   unsigned long lit = 0L;
6092   int bytelit = 0;
6093   resolvedIfx rIfx;
6094
6095
6096   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6097   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6098   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6099   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6100
6101   resolveIfx(&rIfx,ifx);
6102
6103   /* if left is a literal & right is not then exchange them */
6104   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6105       AOP_NEEDSACC(left)) {
6106     operand *tmp = right ;
6107     right = left;
6108     left = tmp;
6109   }
6110
6111   /* if result = right then exchange them */
6112   if(pic16_sameRegs(AOP(result),AOP(right))){
6113     operand *tmp = right ;
6114     right = left;
6115     left = tmp;
6116   }
6117
6118   /* if right is bit then exchange them */
6119   if (AOP_TYPE(right) == AOP_CRY &&
6120       AOP_TYPE(left) != AOP_CRY){
6121     operand *tmp = right ;
6122     right = left;
6123     left = tmp;
6124   }
6125   if(AOP_TYPE(right) == AOP_LIT)
6126     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6127
6128   size = AOP_SIZE(result);
6129
6130   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6131
6132   // if(bit & yy)
6133   // result = bit & yy;
6134   if (AOP_TYPE(left) == AOP_CRY){
6135     // c = bit & literal;
6136     if(AOP_TYPE(right) == AOP_LIT){
6137       if(lit & 1) {
6138         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6139           // no change
6140           goto release;
6141         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6142       } else {
6143         // bit(result) = 0;
6144         if(size && (AOP_TYPE(result) == AOP_CRY)){
6145           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6146           goto release;
6147         }
6148         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6149           jumpIfTrue(ifx);
6150           goto release;
6151         }
6152         pic16_emitcode("clr","c");
6153       }
6154     } else {
6155       if (AOP_TYPE(right) == AOP_CRY){
6156         // c = bit & bit;
6157         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6158         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6159       } else {
6160         // c = bit & val;
6161         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6162         // c = lsb
6163         pic16_emitcode("rrc","a");
6164         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6165       }
6166     }
6167     // bit = c
6168     // val = c
6169     if(size)
6170       pic16_outBitC(result);
6171     // if(bit & ...)
6172     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6173       genIfxJump(ifx, "c");           
6174     goto release ;
6175   }
6176
6177   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6178   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6179   if((AOP_TYPE(right) == AOP_LIT) &&
6180      (AOP_TYPE(result) == AOP_CRY) &&
6181      (AOP_TYPE(left) != AOP_CRY)){
6182     int posbit = isLiteralBit(lit);
6183     /* left &  2^n */
6184     if(posbit){
6185       posbit--;
6186       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6187       // bit = left & 2^n
6188       if(size)
6189         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6190       // if(left &  2^n)
6191       else{
6192         if(ifx){
6193 /*
6194           if(IC_TRUE(ifx)) {
6195             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6196             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6197           } else {
6198             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6199             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6200           }
6201 */
6202           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6203                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6204           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6205           
6206           ifx->generated = 1;
6207         }
6208         goto release;
6209       }
6210     } else {
6211       symbol *tlbl = newiTempLabel(NULL);
6212       int sizel = AOP_SIZE(left);
6213       if(size)
6214         pic16_emitcode("setb","c");
6215       while(sizel--){
6216         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6217           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6218           // byte ==  2^n ?
6219           if((posbit = isLiteralBit(bytelit)) != 0)
6220             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6221           else{
6222             if(bytelit != 0x0FFL)
6223               pic16_emitcode("anl","a,%s",
6224                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6225             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6226           }
6227         }
6228         offset++;
6229       }
6230       // bit = left & literal
6231       if(size){
6232         pic16_emitcode("clr","c");
6233         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6234       }
6235       // if(left & literal)
6236       else{
6237         if(ifx)
6238           jmpTrueOrFalse(ifx, tlbl);
6239         goto release ;
6240       }
6241     }
6242     pic16_outBitC(result);
6243     goto release ;
6244   }
6245
6246   /* if left is same as result */
6247   if(pic16_sameRegs(AOP(result),AOP(left))){
6248     int know_W = -1;
6249     for(;size--; offset++,lit>>=8) {
6250       if(AOP_TYPE(right) == AOP_LIT){
6251         switch(lit & 0xff) {
6252         case 0x00:
6253           /*  and'ing with 0 has clears the result */
6254 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6255           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6256           break;
6257         case 0xff:
6258           /* and'ing with 0xff is a nop when the result and left are the same */
6259           break;
6260
6261         default:
6262           {
6263             int p = my_powof2( (~lit) & 0xff );
6264             if(p>=0) {
6265               /* only one bit is set in the literal, so use a bcf instruction */
6266 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6267               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6268
6269             } else {
6270               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6271               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6272               if(know_W != (lit&0xff))
6273                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6274               know_W = lit &0xff;
6275               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6276             }
6277           }    
6278         }
6279       } else {
6280         if (AOP_TYPE(left) == AOP_ACC) {
6281           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6282         } else {                    
6283           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6284           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6285
6286         }
6287       }
6288     }
6289
6290   } else {
6291     // left & result in different registers
6292     if(AOP_TYPE(result) == AOP_CRY){
6293       // result = bit
6294       // if(size), result in bit
6295       // if(!size && ifx), conditional oper: if(left & right)
6296       symbol *tlbl = newiTempLabel(NULL);
6297       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6298       if(size)
6299         pic16_emitcode("setb","c");
6300       while(sizer--){
6301         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6302         pic16_emitcode("anl","a,%s",
6303                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6304         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6305         offset++;
6306       }
6307       if(size){
6308         CLRC;
6309         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6310         pic16_outBitC(result);
6311       } else if(ifx)
6312         jmpTrueOrFalse(ifx, tlbl);
6313     } else {
6314       for(;(size--);offset++) {
6315         // normal case
6316         // result = left & right
6317         if(AOP_TYPE(right) == AOP_LIT){
6318           int t = (lit >> (offset*8)) & 0x0FFL;
6319           switch(t) { 
6320           case 0x00:
6321             pic16_emitcode("clrf","%s",
6322                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6323             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6324             break;
6325           case 0xff:
6326             pic16_emitcode("movf","%s,w",
6327                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6328             pic16_emitcode("movwf","%s",
6329                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6330             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6331             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6332             break;
6333           default:
6334             pic16_emitcode("movlw","0x%x",t);
6335             pic16_emitcode("andwf","%s,w",
6336                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6337             pic16_emitcode("movwf","%s",
6338                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6339               
6340             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6341             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6342             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6343           }
6344           continue;
6345         }
6346
6347         if (AOP_TYPE(left) == AOP_ACC) {
6348           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6349           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6350         } else {
6351           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6352           pic16_emitcode("andwf","%s,w",
6353                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6354           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6355           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6356         }
6357         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6358         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6359       }
6360     }
6361   }
6362
6363   release :
6364     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6365   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6366   pic16_freeAsmop(result,NULL,ic,TRUE);     
6367 }
6368
6369 /*-----------------------------------------------------------------*/
6370 /* genOr  - code for or                                            */
6371 /*-----------------------------------------------------------------*/
6372 static void genOr (iCode *ic, iCode *ifx)
6373 {
6374     operand *left, *right, *result;
6375     int size, offset=0;
6376     unsigned long lit = 0L;
6377
6378     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6379
6380     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6381     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6382     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6383
6384     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6385
6386     /* if left is a literal & right is not then exchange them */
6387     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6388         AOP_NEEDSACC(left)) {
6389         operand *tmp = right ;
6390         right = left;
6391         left = tmp;
6392     }
6393
6394     /* if result = right then exchange them */
6395     if(pic16_sameRegs(AOP(result),AOP(right))){
6396         operand *tmp = right ;
6397         right = left;
6398         left = tmp;
6399     }
6400
6401     /* if right is bit then exchange them */
6402     if (AOP_TYPE(right) == AOP_CRY &&
6403         AOP_TYPE(left) != AOP_CRY){
6404         operand *tmp = right ;
6405         right = left;
6406         left = tmp;
6407     }
6408
6409     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6410
6411     if(AOP_TYPE(right) == AOP_LIT)
6412         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6413
6414     size = AOP_SIZE(result);
6415
6416     // if(bit | yy)
6417     // xx = bit | yy;
6418     if (AOP_TYPE(left) == AOP_CRY){
6419         if(AOP_TYPE(right) == AOP_LIT){
6420             // c = bit & literal;
6421             if(lit){
6422                 // lit != 0 => result = 1
6423                 if(AOP_TYPE(result) == AOP_CRY){
6424                   if(size)
6425                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6426                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6427                   //     AOP(result)->aopu.aop_dir,
6428                   //     AOP(result)->aopu.aop_dir);
6429                     else if(ifx)
6430                         continueIfTrue(ifx);
6431                     goto release;
6432                 }
6433             } else {
6434                 // lit == 0 => result = left
6435                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6436                     goto release;
6437                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6438             }
6439         } else {
6440             if (AOP_TYPE(right) == AOP_CRY){
6441               if(pic16_sameRegs(AOP(result),AOP(left))){
6442                 // c = bit | bit;
6443                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6444                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6445                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6446
6447                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6448                          AOP(result)->aopu.aop_dir,
6449                          AOP(result)->aopu.aop_dir);
6450                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6451                          AOP(right)->aopu.aop_dir,
6452                          AOP(right)->aopu.aop_dir);
6453                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6454                          AOP(result)->aopu.aop_dir,
6455                          AOP(result)->aopu.aop_dir);
6456               } else {
6457                 if( AOP_TYPE(result) == AOP_ACC) {
6458                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6459                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6460                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6461                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6462
6463                 } else {
6464
6465                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6466                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6467                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6468                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6469
6470                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6471                                  AOP(result)->aopu.aop_dir,
6472                                  AOP(result)->aopu.aop_dir);
6473                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6474                                  AOP(right)->aopu.aop_dir,
6475                                  AOP(right)->aopu.aop_dir);
6476                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6477                                  AOP(left)->aopu.aop_dir,
6478                                  AOP(left)->aopu.aop_dir);
6479                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6480                                  AOP(result)->aopu.aop_dir,
6481                                  AOP(result)->aopu.aop_dir);
6482                 }
6483               }
6484             } else {
6485                 // c = bit | val;
6486                 symbol *tlbl = newiTempLabel(NULL);
6487                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6488
6489
6490                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6491                 if( AOP_TYPE(right) == AOP_ACC) {
6492                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6493                   emitSKPNZ;
6494                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6495                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6496                 }
6497
6498
6499
6500                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6501                     pic16_emitcode(";XXX setb","c");
6502                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6503                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6504                 pic16_toBoolean(right);
6505                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6506                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6507                     jmpTrueOrFalse(ifx, tlbl);
6508                     goto release;
6509                 } else {
6510                     CLRC;
6511                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6512                 }
6513             }
6514         }
6515         // bit = c
6516         // val = c
6517         if(size)
6518             pic16_outBitC(result);
6519         // if(bit | ...)
6520         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6521             genIfxJump(ifx, "c");           
6522         goto release ;
6523     }
6524
6525     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6526     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6527     if((AOP_TYPE(right) == AOP_LIT) &&
6528        (AOP_TYPE(result) == AOP_CRY) &&
6529        (AOP_TYPE(left) != AOP_CRY)){
6530         if(lit){
6531           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6532             // result = 1
6533             if(size)
6534                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6535             else 
6536                 continueIfTrue(ifx);
6537             goto release;
6538         } else {
6539           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6540             // lit = 0, result = boolean(left)
6541             if(size)
6542                 pic16_emitcode(";XXX setb","c");
6543             pic16_toBoolean(right);
6544             if(size){
6545                 symbol *tlbl = newiTempLabel(NULL);
6546                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6547                 CLRC;
6548                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6549             } else {
6550                 genIfxJump (ifx,"a");
6551                 goto release;
6552             }
6553         }
6554         pic16_outBitC(result);
6555         goto release ;
6556     }
6557
6558     /* if left is same as result */
6559     if(pic16_sameRegs(AOP(result),AOP(left))){
6560       int know_W = -1;
6561       for(;size--; offset++,lit>>=8) {
6562         if(AOP_TYPE(right) == AOP_LIT){
6563           if((lit & 0xff) == 0)
6564             /*  or'ing with 0 has no effect */
6565             continue;
6566           else {
6567             int p = my_powof2(lit & 0xff);
6568             if(p>=0) {
6569               /* only one bit is set in the literal, so use a bsf instruction */
6570               pic16_emitpcode(POC_BSF,
6571                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6572             } else {
6573               if(know_W != (lit & 0xff))
6574                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6575               know_W = lit & 0xff;
6576               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6577             }
6578                     
6579           }
6580         } else {
6581           if (AOP_TYPE(left) == AOP_ACC) {
6582             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6583             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6584           } else {                  
6585             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6586             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6587
6588             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6589             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6590
6591           }
6592         }
6593       }
6594     } else {
6595         // left & result in different registers
6596         if(AOP_TYPE(result) == AOP_CRY){
6597             // result = bit
6598             // if(size), result in bit
6599             // if(!size && ifx), conditional oper: if(left | right)
6600             symbol *tlbl = newiTempLabel(NULL);
6601             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6602             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6603
6604
6605             if(size)
6606                 pic16_emitcode(";XXX setb","c");
6607             while(sizer--){
6608                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6609                 pic16_emitcode(";XXX orl","a,%s",
6610                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6611                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6612                 offset++;
6613             }
6614             if(size){
6615                 CLRC;
6616                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6617                 pic16_outBitC(result);
6618             } else if(ifx)
6619                 jmpTrueOrFalse(ifx, tlbl);
6620         } else for(;(size--);offset++){
6621           // normal case
6622           // result = left & right
6623           if(AOP_TYPE(right) == AOP_LIT){
6624             int t = (lit >> (offset*8)) & 0x0FFL;
6625             switch(t) { 
6626             case 0x00:
6627               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6628               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6629
6630               pic16_emitcode("movf","%s,w",
6631                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6632               pic16_emitcode("movwf","%s",
6633                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6634               break;
6635             default:
6636               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6637               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6638               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6639
6640               pic16_emitcode("movlw","0x%x",t);
6641               pic16_emitcode("iorwf","%s,w",
6642                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6643               pic16_emitcode("movwf","%s",
6644                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6645               
6646             }
6647             continue;
6648           }
6649
6650           // faster than result <- left, anl result,right
6651           // and better if result is SFR
6652           if (AOP_TYPE(left) == AOP_ACC) {
6653             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6654             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6655           } else {
6656             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6657             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6658
6659             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6660             pic16_emitcode("iorwf","%s,w",
6661                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6662           }
6663           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6664           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6665         }
6666     }
6667
6668 release :
6669     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6670     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6671     pic16_freeAsmop(result,NULL,ic,TRUE);     
6672 }
6673
6674 /*-----------------------------------------------------------------*/
6675 /* genXor - code for xclusive or                                   */
6676 /*-----------------------------------------------------------------*/
6677 static void genXor (iCode *ic, iCode *ifx)
6678 {
6679   operand *left, *right, *result;
6680   int size, offset=0;
6681   unsigned long lit = 0L;
6682
6683   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6684
6685   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6686   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6687   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6688
6689   /* if left is a literal & right is not ||
6690      if left needs acc & right does not */
6691   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6692       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6693     operand *tmp = right ;
6694     right = left;
6695     left = tmp;
6696   }
6697
6698   /* if result = right then exchange them */
6699   if(pic16_sameRegs(AOP(result),AOP(right))){
6700     operand *tmp = right ;
6701     right = left;
6702     left = tmp;
6703   }
6704
6705   /* if right is bit then exchange them */
6706   if (AOP_TYPE(right) == AOP_CRY &&
6707       AOP_TYPE(left) != AOP_CRY){
6708     operand *tmp = right ;
6709     right = left;
6710     left = tmp;
6711   }
6712   if(AOP_TYPE(right) == AOP_LIT)
6713     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6714
6715   size = AOP_SIZE(result);
6716
6717   // if(bit ^ yy)
6718   // xx = bit ^ yy;
6719   if (AOP_TYPE(left) == AOP_CRY){
6720     if(AOP_TYPE(right) == AOP_LIT){
6721       // c = bit & literal;
6722       if(lit>>1){
6723         // lit>>1  != 0 => result = 1
6724         if(AOP_TYPE(result) == AOP_CRY){
6725           if(size)
6726             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6727             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6728           else if(ifx)
6729             continueIfTrue(ifx);
6730           goto release;
6731         }
6732         pic16_emitcode("setb","c");
6733       } else{
6734         // lit == (0 or 1)
6735         if(lit == 0){
6736           // lit == 0, result = left
6737           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6738             goto release;
6739           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6740         } else{
6741           // lit == 1, result = not(left)
6742           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6743             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6744             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6745             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6746             goto release;
6747           } else {
6748             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6749             pic16_emitcode("cpl","c");
6750           }
6751         }
6752       }
6753
6754     } else {
6755       // right != literal
6756       symbol *tlbl = newiTempLabel(NULL);
6757       if (AOP_TYPE(right) == AOP_CRY){
6758         // c = bit ^ bit;
6759         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6760       }
6761       else{
6762         int sizer = AOP_SIZE(right);
6763         // c = bit ^ val
6764         // if val>>1 != 0, result = 1
6765         pic16_emitcode("setb","c");
6766         while(sizer){
6767           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6768           if(sizer == 1)
6769             // test the msb of the lsb
6770             pic16_emitcode("anl","a,#0xfe");
6771           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6772           sizer--;
6773         }
6774         // val = (0,1)
6775         pic16_emitcode("rrc","a");
6776       }
6777       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6778       pic16_emitcode("cpl","c");
6779       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6780     }
6781     // bit = c
6782     // val = c
6783     if(size)
6784       pic16_outBitC(result);
6785     // if(bit | ...)
6786     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6787       genIfxJump(ifx, "c");           
6788     goto release ;
6789   }
6790
6791   if(pic16_sameRegs(AOP(result),AOP(left))){
6792     /* if left is same as result */
6793     for(;size--; offset++) {
6794       if(AOP_TYPE(right) == AOP_LIT){
6795         int t  = (lit >> (offset*8)) & 0x0FFL;
6796         if(t == 0x00L)
6797           continue;
6798         else
6799           if (IS_AOP_PREG(left)) {
6800             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6801             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6802             pic16_aopPut(AOP(result),"a",offset);
6803           } else {
6804             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6805             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6806             pic16_emitcode("xrl","%s,%s",
6807                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6808                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6809           }
6810       } else {
6811         if (AOP_TYPE(left) == AOP_ACC)
6812           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6813         else {
6814           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6815           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6816 /*
6817           if (IS_AOP_PREG(left)) {
6818             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6819             pic16_aopPut(AOP(result),"a",offset);
6820           } else
6821             pic16_emitcode("xrl","%s,a",
6822                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6823 */
6824         }
6825       }
6826     }
6827   } else {
6828     // left & result in different registers
6829     if(AOP_TYPE(result) == AOP_CRY){
6830       // result = bit
6831       // if(size), result in bit
6832       // if(!size && ifx), conditional oper: if(left ^ right)
6833       symbol *tlbl = newiTempLabel(NULL);
6834       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6835       if(size)
6836         pic16_emitcode("setb","c");
6837       while(sizer--){
6838         if((AOP_TYPE(right) == AOP_LIT) &&
6839            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6840           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6841         } else {
6842           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6843           pic16_emitcode("xrl","a,%s",
6844                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6845         }
6846         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6847         offset++;
6848       }
6849       if(size){
6850         CLRC;
6851         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6852         pic16_outBitC(result);
6853       } else if(ifx)
6854         jmpTrueOrFalse(ifx, tlbl);
6855     } else for(;(size--);offset++){
6856       // normal case
6857       // result = left & right
6858       if(AOP_TYPE(right) == AOP_LIT){
6859         int t = (lit >> (offset*8)) & 0x0FFL;
6860         switch(t) { 
6861         case 0x00:
6862           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6863           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6864           pic16_emitcode("movf","%s,w",
6865                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6866           pic16_emitcode("movwf","%s",
6867                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6868           break;
6869         case 0xff:
6870           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6871           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6872           pic16_emitcode("comf","%s,w",
6873                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6874           pic16_emitcode("movwf","%s",
6875                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6876           break;
6877         default:
6878           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6879           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6880           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6881           pic16_emitcode("movlw","0x%x",t);
6882           pic16_emitcode("xorwf","%s,w",
6883                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6884           pic16_emitcode("movwf","%s",
6885                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6886
6887         }
6888         continue;
6889       }
6890
6891       // faster than result <- left, anl result,right
6892       // and better if result is SFR
6893       if (AOP_TYPE(left) == AOP_ACC) {
6894         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6895         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6896       } else {
6897         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6898         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6899         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6900         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6901       }
6902       if ( AOP_TYPE(result) != AOP_ACC){
6903         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6904         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6905       }
6906     }
6907   }
6908
6909   release :
6910     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6911   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6912   pic16_freeAsmop(result,NULL,ic,TRUE);     
6913 }
6914
6915 /*-----------------------------------------------------------------*/
6916 /* genInline - write the inline code out                           */
6917 /*-----------------------------------------------------------------*/
6918 static void genInline (iCode *ic)
6919 {
6920   char *buffer, *bp, *bp1;
6921     
6922         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6923
6924         _G.inLine += (!options.asmpeep);
6925
6926         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6927         strcpy(buffer,IC_INLINE(ic));
6928
6929 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6930
6931         /* emit each line as a code */
6932         while (*bp) {
6933                 if (*bp == '\n') {
6934                         *bp++ = '\0';
6935
6936                         if(*bp1)
6937                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6938                         bp1 = bp;
6939                 } else {
6940                         if (*bp == ':') {
6941                                 bp++;
6942                                 *bp = '\0';
6943                                 bp++;
6944
6945                                 /* print label, use this special format with NULL directive
6946                                  * to denote that the argument should not be indented with tab */
6947                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6948                                 bp1 = bp;
6949                         } else
6950                                 bp++;
6951                 }
6952         }
6953
6954         if ((bp1 != bp) && *bp1)
6955                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6956
6957
6958     Safe_free(buffer);
6959
6960     _G.inLine -= (!options.asmpeep);
6961 }
6962
6963 /*-----------------------------------------------------------------*/
6964 /* genRRC - rotate right with carry                                */
6965 /*-----------------------------------------------------------------*/
6966 static void genRRC (iCode *ic)
6967 {
6968   operand *left , *result ;
6969   int size, offset = 0, same;
6970
6971   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6972
6973   /* rotate right with carry */
6974   left = IC_LEFT(ic);
6975   result=IC_RESULT(ic);
6976   pic16_aopOp (left,ic,FALSE);
6977   pic16_aopOp (result,ic,FALSE);
6978
6979   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6980
6981   same = pic16_sameRegs(AOP(result),AOP(left));
6982
6983   size = AOP_SIZE(result);    
6984
6985   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6986
6987   /* get the lsb and put it into the carry */
6988   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6989
6990   offset = 0 ;
6991
6992   while(size--) {
6993
6994     if(same) {
6995       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6996     } else {
6997       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6998       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6999     }
7000
7001     offset++;
7002   }
7003
7004   pic16_freeAsmop(left,NULL,ic,TRUE);
7005   pic16_freeAsmop(result,NULL,ic,TRUE);
7006 }
7007
7008 /*-----------------------------------------------------------------*/
7009 /* genRLC - generate code for rotate left with carry               */
7010 /*-----------------------------------------------------------------*/
7011 static void genRLC (iCode *ic)
7012 {    
7013   operand *left , *result ;
7014   int size, offset = 0;
7015   int same;
7016
7017   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7018   /* rotate right with carry */
7019   left = IC_LEFT(ic);
7020   result=IC_RESULT(ic);
7021   pic16_aopOp (left,ic,FALSE);
7022   pic16_aopOp (result,ic,FALSE);
7023
7024   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7025
7026   same = pic16_sameRegs(AOP(result),AOP(left));
7027
7028   /* move it to the result */
7029   size = AOP_SIZE(result);    
7030
7031   /* get the msb and put it into the carry */
7032   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7033
7034   offset = 0 ;
7035
7036   while(size--) {
7037
7038     if(same) {
7039       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7040     } else {
7041       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7042       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7043     }
7044
7045     offset++;
7046   }
7047
7048
7049   pic16_freeAsmop(left,NULL,ic,TRUE);
7050   pic16_freeAsmop(result,NULL,ic,TRUE);
7051 }
7052
7053
7054 /* gpasm can get the highest order bit with HIGH/UPPER
7055  * so the following probably is not needed -- VR */
7056  
7057 /*-----------------------------------------------------------------*/
7058 /* genGetHbit - generates code get highest order bit               */
7059 /*-----------------------------------------------------------------*/
7060 static void genGetHbit (iCode *ic)
7061 {
7062     operand *left, *result;
7063     left = IC_LEFT(ic);
7064     result=IC_RESULT(ic);
7065     pic16_aopOp (left,ic,FALSE);
7066     pic16_aopOp (result,ic,FALSE);
7067
7068     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7069     /* get the highest order byte into a */
7070     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7071     if(AOP_TYPE(result) == AOP_CRY){
7072         pic16_emitcode("rlc","a");
7073         pic16_outBitC(result);
7074     }
7075     else{
7076         pic16_emitcode("rl","a");
7077         pic16_emitcode("anl","a,#0x01");
7078         pic16_outAcc(result);
7079     }
7080
7081
7082     pic16_freeAsmop(left,NULL,ic,TRUE);
7083     pic16_freeAsmop(result,NULL,ic,TRUE);
7084 }
7085
7086 #if 0
7087 /*-----------------------------------------------------------------*/
7088 /* AccRol - rotate left accumulator by known count                 */
7089 /*-----------------------------------------------------------------*/
7090 static void AccRol (int shCount)
7091 {
7092     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7093     shCount &= 0x0007;              // shCount : 0..7
7094     switch(shCount){
7095         case 0 :
7096             break;
7097         case 1 :
7098             pic16_emitcode("rl","a");
7099             break;
7100         case 2 :
7101             pic16_emitcode("rl","a");
7102             pic16_emitcode("rl","a");
7103             break;
7104         case 3 :
7105             pic16_emitcode("swap","a");
7106             pic16_emitcode("rr","a");
7107             break;
7108         case 4 :
7109             pic16_emitcode("swap","a");
7110             break;
7111         case 5 :
7112             pic16_emitcode("swap","a");
7113             pic16_emitcode("rl","a");
7114             break;
7115         case 6 :
7116             pic16_emitcode("rr","a");
7117             pic16_emitcode("rr","a");
7118             break;
7119         case 7 :
7120             pic16_emitcode("rr","a");
7121             break;
7122     }
7123 }
7124 #endif
7125
7126 /*-----------------------------------------------------------------*/
7127 /* AccLsh - left shift accumulator by known count                  */
7128 /*-----------------------------------------------------------------*/
7129 static void AccLsh (int shCount)
7130 {
7131         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7132         switch(shCount){
7133                 case 0 :
7134                         return;
7135                         break;
7136                 case 1 :
7137                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7138                         break;
7139                 case 2 :
7140                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7141                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7142                         break;
7143                 case 3 :
7144                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7145                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7146                         break;
7147                 case 4 :
7148                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7149                         break;
7150                 case 5 :
7151                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7152                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7153                         break;
7154                 case 6 :
7155                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7156                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7157                         break;
7158                 case 7 :
7159                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7160                         break;
7161         }
7162
7163         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7164 }
7165
7166 /*-----------------------------------------------------------------*/
7167 /* AccRsh - right shift accumulator by known count                 */
7168 /*-----------------------------------------------------------------*/
7169 static void AccRsh (int shCount, int andmask)
7170 {
7171         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7172         switch(shCount){
7173                 case 0 :
7174                         return; break;
7175                 case 1 :
7176                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7177 //                      andmask = 0;    /* no need */
7178                         break;
7179                 case 2 :
7180                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7181                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7182 //                      andmask = 0;    /* no need */
7183                         break;
7184                 case 3 :
7185                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7186                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7187                         break;
7188                 case 4 :
7189                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7190                         break;
7191                 case 5 :
7192                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7193                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7194                         break;
7195                 case 6 :
7196                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7197                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7198                         break;
7199                 case 7 :
7200                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7201                         break;
7202         }
7203         
7204         if(andmask)
7205                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7206         else
7207                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7208 }
7209
7210 #if 0
7211 /*-----------------------------------------------------------------*/
7212 /* AccSRsh - signed right shift accumulator by known count                 */
7213 /*-----------------------------------------------------------------*/
7214 static void AccSRsh (int shCount)
7215 {
7216     symbol *tlbl ;
7217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7218     if(shCount != 0){
7219         if(shCount == 1){
7220             pic16_emitcode("mov","c,acc.7");
7221             pic16_emitcode("rrc","a");
7222         } else if(shCount == 2){
7223             pic16_emitcode("mov","c,acc.7");
7224             pic16_emitcode("rrc","a");
7225             pic16_emitcode("mov","c,acc.7");
7226             pic16_emitcode("rrc","a");
7227         } else {
7228             tlbl = newiTempLabel(NULL);
7229             /* rotate right accumulator */
7230             AccRol(8 - shCount);
7231             /* and kill the higher order bits */
7232             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7233             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7234             pic16_emitcode("orl","a,#0x%02x",
7235                      (unsigned char)~SRMask[shCount]);
7236             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7237         }
7238     }
7239 }
7240 #endif
7241 /*-----------------------------------------------------------------*/
7242 /* shiftR1Left2Result - shift right one byte from left to result   */
7243 /*-----------------------------------------------------------------*/
7244 static void shiftR1Left2ResultSigned (operand *left, int offl,
7245                                 operand *result, int offr,
7246                                 int shCount)
7247 {
7248   int same;
7249
7250   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7251
7252   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7253
7254   switch(shCount) {
7255   case 1:
7256     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7257     if(same) 
7258       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7259     else {
7260       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7261       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7262     }
7263
7264     break;
7265   case 2:
7266
7267     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7268     if(same) 
7269       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7270     else {
7271       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7272       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7273     }
7274     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7275     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7276
7277     break;
7278
7279   case 3:
7280     if(same)
7281       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7282     else {
7283       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7284       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7285     }
7286
7287     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7288     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7289     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7290
7291     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7292     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7293
7294     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7295     break;
7296
7297   case 4:
7298     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7299     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7300     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7301     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7302     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7303     break;
7304   case 5:
7305     if(same) {
7306       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7307     } else {
7308       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7309       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7310     }
7311     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7312     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7313     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7314     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7315     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7316     break;
7317
7318   case 6:
7319     if(same) {
7320       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7321       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7322       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7323       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7324       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7325       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7326     } else {
7327       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7328       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7329       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7330       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7331       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7332     }
7333     break;
7334
7335   case 7:
7336     if(same) {
7337       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7338       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7339       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7340       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7341     } else {
7342       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7343       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7344       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7345     }
7346
7347   default:
7348     break;
7349   }
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* shiftR1Left2Result - shift right one byte from left to result   */
7354 /*-----------------------------------------------------------------*/
7355 static void shiftR1Left2Result (operand *left, int offl,
7356                                 operand *result, int offr,
7357                                 int shCount, int sign)
7358 {
7359   int same;
7360
7361   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7362
7363   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7364
7365   /* Copy the msb into the carry if signed. */
7366   if(sign) {
7367     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7368     return;
7369   }
7370
7371
7372
7373   switch(shCount) {
7374   case 1:
7375     emitCLRC;
7376     if(same) 
7377       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7378     else {
7379       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7380       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7381     }
7382     break;
7383   case 2:
7384     emitCLRC;
7385     if(same) {
7386       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7387     } else {
7388       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7389       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7390     }
7391     emitCLRC;
7392     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7393
7394     break;
7395   case 3:
7396     if(same)
7397       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7398     else {
7399       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7400       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7401     }
7402
7403     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7404     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7405     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7406     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7407     break;
7408       
7409   case 4:
7410     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7411     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7412     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7413     break;
7414
7415   case 5:
7416     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7417     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7418     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7419     emitCLRC;
7420     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7421
7422     break;
7423   case 6:
7424
7425     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7426     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7427     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7428     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7429     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7430     break;
7431
7432   case 7:
7433
7434     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7435     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7436     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7437
7438     break;
7439
7440   default:
7441     break;
7442   }
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* shiftL1Left2Result - shift left one byte from left to result    */
7447 /*-----------------------------------------------------------------*/
7448 static void shiftL1Left2Result (operand *left, int offl,
7449                                 operand *result, int offr, int shCount)
7450 {
7451   int same;
7452
7453   //    char *l;
7454   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7455
7456   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7457   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7458     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7459     //    MOVA(l);
7460     /* shift left accumulator */
7461     //AccLsh(shCount); // don't comment out just yet...
7462   //    pic16_aopPut(AOP(result),"a",offr);
7463
7464   switch(shCount) {
7465   case 1:
7466     /* Shift left 1 bit position */
7467     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7468     if(same) {
7469       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7470     } else {
7471       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7472       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7473     }
7474     break;
7475   case 2:
7476     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7477     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7478     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7479     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7480     break;
7481   case 3:
7482     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7483     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7484     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7485     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7486     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7487     break;
7488   case 4:
7489     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7490     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7491     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7492     break;
7493   case 5:
7494     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7495     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7496     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7497     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7498     break;
7499   case 6:
7500     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7501     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7502     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7503     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7504     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7505     break;
7506   case 7:
7507     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7508     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7509     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7510     break;
7511
7512   default:
7513     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7514   }
7515
7516 }
7517
7518 /*-----------------------------------------------------------------*/
7519 /* movLeft2Result - move byte from left to result                  */
7520 /*-----------------------------------------------------------------*/
7521 static void movLeft2Result (operand *left, int offl,
7522                             operand *result, int offr)
7523 {
7524   char *l;
7525   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7526   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7527     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7528
7529     if (*l == '@' && (IS_AOP_PREG(result))) {
7530       pic16_emitcode("mov","a,%s",l);
7531       pic16_aopPut(AOP(result),"a",offr);
7532     } else {
7533       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7534       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7535     }
7536   }
7537 }
7538
7539 /*-----------------------------------------------------------------*/
7540 /* shiftL2Left2Result - shift left two bytes from left to result   */
7541 /*-----------------------------------------------------------------*/
7542 static void shiftL2Left2Result (operand *left, int offl,
7543                                 operand *result, int offr, int shCount)
7544 {
7545   int same = pic16_sameRegs(AOP(result), AOP(left));
7546   int i;
7547
7548   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7549
7550   if (same && (offl != offr)) { // shift bytes
7551     if (offr > offl) {
7552        for(i=1;i>-1;i--) {
7553          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7554          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7555        }
7556     } else { // just treat as different later on
7557                 same = 0;
7558     }
7559   }
7560
7561   if(same) {
7562     switch(shCount) {
7563     case 0:
7564       break;
7565     case 1:
7566     case 2:
7567     case 3:
7568
7569       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7570       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7571       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7572
7573       while(--shCount) {
7574                 emitCLRC;
7575                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7576                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7577       }
7578
7579       break;
7580     case 4:
7581     case 5:
7582       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7583       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7584       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7585       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7586       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7587       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7588       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7589       if(shCount >=5) {
7590                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7591                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7592       }
7593       break;
7594     case 6:
7595       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7596       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7597       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7598       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7599       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7600       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7601       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7602       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7603       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7604       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7605       break;
7606     case 7:
7607       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7608       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7609       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7610       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7611       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7612     }
7613
7614   } else {
7615     switch(shCount) {
7616     case 0:
7617       break;
7618     case 1:
7619     case 2:
7620     case 3:
7621       /* note, use a mov/add for the shift since the mov has a
7622          chance of getting optimized out */
7623       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7624       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7625       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7626       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7627       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7628
7629       while(--shCount) {
7630                 emitCLRC;
7631                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7632                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7633       }
7634       break;
7635
7636     case 4:
7637     case 5:
7638       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7639       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7640       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7641       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7642       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7643       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7644       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7645       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7646
7647
7648       if(shCount == 5) {
7649                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7650                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7651       }
7652       break;
7653     case 6:
7654       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7655       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7656       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7657       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7658
7659       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7660       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7661       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7662       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7663       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7664       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7665       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7666       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7667       break;
7668     case 7:
7669       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7670       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7671       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7672       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7673       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7674     }
7675   }
7676
7677 }
7678 /*-----------------------------------------------------------------*/
7679 /* shiftR2Left2Result - shift right two bytes from left to result  */
7680 /*-----------------------------------------------------------------*/
7681 static void shiftR2Left2Result (operand *left, int offl,
7682                                 operand *result, int offr,
7683                                 int shCount, int sign)
7684 {
7685   int same = pic16_sameRegs(AOP(result), AOP(left));
7686   int i;
7687   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7688
7689   if (same && (offl != offr)) { // shift right bytes
7690     if (offr < offl) {
7691        for(i=0;i<2;i++) {
7692          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7693          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7694        }
7695     } else { // just treat as different later on
7696                 same = 0;
7697     }
7698   }
7699
7700   switch(shCount) {
7701   case 0:
7702     break;
7703   case 1:
7704   case 2:
7705   case 3:
7706     if(sign)
7707       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7708     else
7709       emitCLRC;
7710
7711     if(same) {
7712       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7713       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7714     } else {
7715       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7716       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7717       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7718       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7719     }
7720
7721     while(--shCount) {
7722       if(sign)
7723                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7724       else
7725                 emitCLRC;
7726       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7727       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7728     }
7729     break;
7730   case 4:
7731   case 5:
7732     if(same) {
7733
7734       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7735       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7736       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7737
7738       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7739       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7740       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7741       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7742     } else {
7743       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7744       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7745       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7746
7747       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7748       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7749       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7750       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7751       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7752     }
7753
7754     if(shCount >=5) {
7755       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7756       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7757     }
7758
7759     if(sign) {
7760       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7761       pic16_emitpcode(POC_BTFSC, 
7762                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7763       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7764     }
7765
7766     break;
7767
7768   case 6:
7769     if(same) {
7770
7771       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7772       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7773
7774       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7775       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7776       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7777       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7778       if(sign) {
7779         pic16_emitpcode(POC_BTFSC, 
7780                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7781         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7782       }
7783       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7784       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7785       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7786       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7787     } else {
7788       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7789       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7790       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7791       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7792       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7793       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7794       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7795       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7796       if(sign) {
7797         pic16_emitpcode(POC_BTFSC, 
7798                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7799         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7800       }
7801       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7802       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7803
7804         
7805     }
7806
7807     break;
7808   case 7:
7809     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7810     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7811     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7812     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7813     if(sign) {
7814       emitSKPNC;
7815       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7816     } else 
7817       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7818   }
7819 }
7820
7821
7822 /*-----------------------------------------------------------------*/
7823 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7824 /*-----------------------------------------------------------------*/
7825 static void shiftLLeftOrResult (operand *left, int offl,
7826                                 operand *result, int offr, int shCount)
7827 {
7828     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7829
7830     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7831     /* shift left accumulator */
7832     AccLsh(shCount);
7833     /* or with result */
7834     /* back to result */
7835     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7836 }
7837
7838 /*-----------------------------------------------------------------*/
7839 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7840 /*-----------------------------------------------------------------*/
7841 static void shiftRLeftOrResult (operand *left, int offl,
7842                                 operand *result, int offr, int shCount)
7843 {
7844     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7845     
7846     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7847     /* shift right accumulator */
7848     AccRsh(shCount, 1);
7849     /* or with result */
7850     /* back to result */
7851     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7852 }
7853
7854 /*-----------------------------------------------------------------*/
7855 /* genlshOne - left shift a one byte quantity by known count       */
7856 /*-----------------------------------------------------------------*/
7857 static void genlshOne (operand *result, operand *left, int shCount)
7858 {       
7859     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7860     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7861 }
7862
7863 /*-----------------------------------------------------------------*/
7864 /* genlshTwo - left shift two bytes by known amount != 0           */
7865 /*-----------------------------------------------------------------*/
7866 static void genlshTwo (operand *result,operand *left, int shCount)
7867 {
7868     int size;
7869     
7870     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7871     size = pic16_getDataSize(result);
7872
7873     /* if shCount >= 8 */
7874     if (shCount >= 8) {
7875         shCount -= 8 ;
7876
7877         if (size > 1){
7878             if (shCount)
7879                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7880             else 
7881                 movLeft2Result(left, LSB, result, MSB16);
7882         }
7883         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7884     }
7885
7886     /*  1 <= shCount <= 7 */
7887     else {  
7888         if(size == 1)
7889             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7890         else 
7891             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7892     }
7893 }
7894
7895 /*-----------------------------------------------------------------*/
7896 /* shiftLLong - shift left one long from left to result            */
7897 /* offr = LSB or MSB16                                             */
7898 /*-----------------------------------------------------------------*/
7899 static void shiftLLong (operand *left, operand *result, int offr )
7900 {
7901     int size = AOP_SIZE(result);
7902     int same = pic16_sameRegs(AOP(left),AOP(result));
7903         int i;
7904
7905     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7906
7907         if (same && (offr == MSB16)) { //shift one byte
7908                 for(i=size-1;i>=MSB16;i--) {
7909                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7910                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7911                 }
7912         } else {
7913                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7914         }
7915         
7916     if (size >= LSB+offr ){
7917                 if (same) {
7918                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7919                 } else {
7920                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7921                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7922                 }
7923          }
7924
7925     if(size >= MSB16+offr){
7926                 if (same) {
7927                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7928                 } else {
7929                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7930                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7931                 }
7932     }
7933
7934     if(size >= MSB24+offr){
7935                 if (same) {
7936                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7937                 } else {
7938                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7939                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7940                 }
7941     }
7942
7943     if(size > MSB32+offr){
7944                 if (same) {
7945                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7946                 } else {
7947                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7948                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7949                 }
7950     }
7951     if(offr != LSB)
7952                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7953
7954 }
7955
7956 /*-----------------------------------------------------------------*/
7957 /* genlshFour - shift four byte by a known amount != 0             */
7958 /*-----------------------------------------------------------------*/
7959 static void genlshFour (operand *result, operand *left, int shCount)
7960 {
7961     int size;
7962
7963     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7964     size = AOP_SIZE(result);
7965
7966     /* if shifting more that 3 bytes */
7967     if (shCount >= 24 ) {
7968         shCount -= 24;
7969         if (shCount)
7970             /* lowest order of left goes to the highest
7971             order of the destination */
7972             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7973         else
7974             movLeft2Result(left, LSB, result, MSB32);
7975
7976                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7977                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7978                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7979
7980         return;
7981     }
7982
7983     /* more than two bytes */
7984     else if ( shCount >= 16 ) {
7985         /* lower order two bytes goes to higher order two bytes */
7986         shCount -= 16;
7987         /* if some more remaining */
7988         if (shCount)
7989             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7990         else {
7991             movLeft2Result(left, MSB16, result, MSB32);
7992             movLeft2Result(left, LSB, result, MSB24);
7993         }
7994                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7995                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7996         return;
7997     }    
7998
7999     /* if more than 1 byte */
8000     else if ( shCount >= 8 ) {
8001         /* lower order three bytes goes to higher order  three bytes */
8002         shCount -= 8;
8003         if(size == 2){
8004             if(shCount)
8005                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8006             else
8007                 movLeft2Result(left, LSB, result, MSB16);
8008         }
8009         else{   /* size = 4 */
8010             if(shCount == 0){
8011                 movLeft2Result(left, MSB24, result, MSB32);
8012                 movLeft2Result(left, MSB16, result, MSB24);
8013                 movLeft2Result(left, LSB, result, MSB16);
8014                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8015             }
8016             else if(shCount == 1)
8017                 shiftLLong(left, result, MSB16);
8018             else{
8019                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8020                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8021                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8022                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8023             }
8024         }
8025     }
8026
8027     /* 1 <= shCount <= 7 */
8028     else if(shCount <= 3)
8029     { 
8030         shiftLLong(left, result, LSB);
8031         while(--shCount >= 1)
8032             shiftLLong(result, result, LSB);
8033     }
8034     /* 3 <= shCount <= 7, optimize */
8035     else{
8036         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8037         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8038         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8039     }
8040 }
8041
8042 /*-----------------------------------------------------------------*/
8043 /* genLeftShiftLiteral - left shifting by known count              */
8044 /*-----------------------------------------------------------------*/
8045 static void genLeftShiftLiteral (operand *left,
8046                                  operand *right,
8047                                  operand *result,
8048                                  iCode *ic)
8049 {    
8050     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8051     int size;
8052
8053     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8054     pic16_freeAsmop(right,NULL,ic,TRUE);
8055
8056     pic16_aopOp(left,ic,FALSE);
8057     pic16_aopOp(result,ic,FALSE);
8058
8059     size = getSize(operandType(result));
8060
8061 #if VIEW_SIZE
8062     pic16_emitcode("; shift left ","result %d, left %d",size,
8063              AOP_SIZE(left));
8064 #endif
8065
8066     /* I suppose that the left size >= result size */
8067     if(shCount == 0){
8068         while(size--){
8069             movLeft2Result(left, size, result, size);
8070         }
8071     }
8072
8073     else if(shCount >= (size * 8))
8074         while(size--)
8075             pic16_aopPut(AOP(result),zero,size);
8076     else{
8077         switch (size) {
8078             case 1:
8079                 genlshOne (result,left,shCount);
8080                 break;
8081
8082             case 2:
8083             case 3:
8084                 genlshTwo (result,left,shCount);
8085                 break;
8086
8087             case 4:
8088                 genlshFour (result,left,shCount);
8089                 break;
8090         }
8091     }
8092     pic16_freeAsmop(left,NULL,ic,TRUE);
8093     pic16_freeAsmop(result,NULL,ic,TRUE);
8094 }
8095
8096 /*-----------------------------------------------------------------*
8097  * genMultiAsm - repeat assembly instruction for size of register.
8098  * if endian == 1, then the high byte (i.e base address + size of 
8099  * register) is used first else the low byte is used first;
8100  *-----------------------------------------------------------------*/
8101 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8102 {
8103
8104   int offset = 0;
8105
8106   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8107
8108   if(!reg)
8109     return;
8110
8111   if(!endian) {
8112     endian = 1;
8113   } else {
8114     endian = -1;
8115     offset = size-1;
8116   }
8117
8118   while(size--) {
8119     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8120     offset += endian;
8121   }
8122
8123 }
8124 /*-----------------------------------------------------------------*/
8125 /* genLeftShift - generates code for left shifting                 */
8126 /*-----------------------------------------------------------------*/
8127 static void genLeftShift (iCode *ic)
8128 {
8129   operand *left,*right, *result;
8130   int size, offset;
8131   char *l;
8132   symbol *tlbl , *tlbl1;
8133   pCodeOp *pctemp;
8134
8135   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8136
8137   right = IC_RIGHT(ic);
8138   left  = IC_LEFT(ic);
8139   result = IC_RESULT(ic);
8140
8141   pic16_aopOp(right,ic,FALSE);
8142
8143   /* if the shift count is known then do it 
8144      as efficiently as possible */
8145   if (AOP_TYPE(right) == AOP_LIT) {
8146     genLeftShiftLiteral (left,right,result,ic);
8147     return ;
8148   }
8149
8150   /* shift count is unknown then we have to form 
8151      a loop get the loop count in B : Note: we take
8152      only the lower order byte since shifting
8153      more that 32 bits make no sense anyway, ( the
8154      largest size of an object can be only 32 bits ) */  
8155
8156     
8157   pic16_aopOp(left,ic,FALSE);
8158   pic16_aopOp(result,ic,FALSE);
8159
8160   /* now move the left to the result if they are not the
8161      same */
8162   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8163       AOP_SIZE(result) > 1) {
8164
8165     size = AOP_SIZE(result);
8166     offset=0;
8167     while (size--) {
8168       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8169       if (*l == '@' && (IS_AOP_PREG(result))) {
8170
8171         pic16_emitcode("mov","a,%s",l);
8172         pic16_aopPut(AOP(result),"a",offset);
8173       } else {
8174         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8175         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8176         //pic16_aopPut(AOP(result),l,offset);
8177       }
8178       offset++;
8179     }
8180   }
8181
8182   size = AOP_SIZE(result);
8183
8184   /* if it is only one byte then */
8185   if (size == 1) {
8186     if(optimized_for_speed) {
8187       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8188       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8189       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8190       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8191       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8192       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8193       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8194       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8195       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8196       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8197       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8198       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8199     } else {
8200
8201       tlbl = newiTempLabel(NULL);
8202       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8203                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8204                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8205       }
8206
8207       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8208       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8209       pic16_emitpLabel(tlbl->key);
8210       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8211       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8212       emitSKPC;
8213       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8214     }
8215     goto release ;
8216   }
8217     
8218   if (pic16_sameRegs(AOP(left),AOP(result))) {
8219
8220     tlbl = newiTempLabel(NULL);
8221     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8222     genMultiAsm(POC_RRCF, result, size,1);
8223     pic16_emitpLabel(tlbl->key);
8224     genMultiAsm(POC_RLCF, result, size,0);
8225     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8226     emitSKPC;
8227     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8228     goto release;
8229   }
8230
8231   //tlbl = newiTempLabel(NULL);
8232   //offset = 0 ;   
8233   //tlbl1 = newiTempLabel(NULL);
8234
8235   //reAdjustPreg(AOP(result));    
8236     
8237   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8238   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8239   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8240   //MOVA(l);
8241   //pic16_emitcode("add","a,acc");         
8242   //pic16_aopPut(AOP(result),"a",offset++);
8243   //while (--size) {
8244   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8245   //  MOVA(l);
8246   //  pic16_emitcode("rlc","a");         
8247   //  pic16_aopPut(AOP(result),"a",offset++);
8248   //}
8249   //reAdjustPreg(AOP(result));
8250
8251   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8252   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8253
8254
8255   tlbl = newiTempLabel(NULL);
8256   tlbl1= newiTempLabel(NULL);
8257
8258   size = AOP_SIZE(result);
8259   offset = 1;
8260
8261   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8262
8263   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8264
8265   /* offset should be 0, 1 or 3 */
8266   
8267   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8268   emitSKPNZ;
8269   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8270
8271   pic16_emitpcode(POC_MOVWF, pctemp);
8272
8273
8274   pic16_emitpLabel(tlbl->key);
8275
8276   emitCLRC;
8277   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8278   while(--size)
8279     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8280
8281   pic16_emitpcode(POC_DECFSZ,  pctemp);
8282   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8283   pic16_emitpLabel(tlbl1->key);
8284
8285   pic16_popReleaseTempReg(pctemp);
8286
8287
8288  release:
8289   pic16_freeAsmop (right,NULL,ic,TRUE);
8290   pic16_freeAsmop(left,NULL,ic,TRUE);
8291   pic16_freeAsmop(result,NULL,ic,TRUE);
8292 }
8293
8294 /*-----------------------------------------------------------------*/
8295 /* genrshOne - right shift a one byte quantity by known count      */
8296 /*-----------------------------------------------------------------*/
8297 static void genrshOne (operand *result, operand *left,
8298                        int shCount, int sign)
8299 {
8300     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8301     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8302 }
8303
8304 /*-----------------------------------------------------------------*/
8305 /* genrshTwo - right shift two bytes by known amount != 0          */
8306 /*-----------------------------------------------------------------*/
8307 static void genrshTwo (operand *result,operand *left,
8308                        int shCount, int sign)
8309 {
8310   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8311   /* if shCount >= 8 */
8312   if (shCount >= 8) {
8313     shCount -= 8 ;
8314     if (shCount)
8315       shiftR1Left2Result(left, MSB16, result, LSB,
8316                          shCount, sign);
8317     else
8318       movLeft2Result(left, MSB16, result, LSB);
8319
8320     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8321
8322     if(sign) {
8323       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8324       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8325     }
8326   }
8327
8328   /*  1 <= shCount <= 7 */
8329   else
8330     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8331 }
8332
8333 /*-----------------------------------------------------------------*/
8334 /* shiftRLong - shift right one long from left to result           */
8335 /* offl = LSB or MSB16                                             */
8336 /*-----------------------------------------------------------------*/
8337 static void shiftRLong (operand *left, int offl,
8338                         operand *result, int sign)
8339 {
8340     int size = AOP_SIZE(result);
8341     int same = pic16_sameRegs(AOP(left),AOP(result));
8342     int i;
8343     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8344
8345         if (same && (offl == MSB16)) { //shift one byte right
8346                 for(i=MSB16;i<size;i++) {
8347                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8348                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8349                 }
8350         }
8351
8352     if(sign)
8353                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8354         else
8355                 emitCLRC;
8356
8357         if (same) {
8358                 if (offl == LSB)
8359                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8360         } else {
8361         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8362         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8363         }
8364
8365     if(offl == MSB16) {
8366         /* add sign of "a" */
8367         pic16_addSign(result, MSB32, sign);
8368         }
8369
8370         if (same) {
8371         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8372         } else {
8373         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8374         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8375         }
8376         
8377         if (same) {
8378         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8379         } else {
8380         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8381         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8382         }
8383
8384         if (same) {
8385         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8386         } else {
8387         if(offl == LSB){
8388                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8389                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8390         }
8391         }
8392 }
8393
8394 /*-----------------------------------------------------------------*/
8395 /* genrshFour - shift four byte by a known amount != 0             */
8396 /*-----------------------------------------------------------------*/
8397 static void genrshFour (operand *result, operand *left,
8398                         int shCount, int sign)
8399 {
8400   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8401   /* if shifting more that 3 bytes */
8402   if(shCount >= 24 ) {
8403     shCount -= 24;
8404     if(shCount)
8405       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8406     else
8407       movLeft2Result(left, MSB32, result, LSB);
8408
8409     pic16_addSign(result, MSB16, sign);
8410   }
8411   else if(shCount >= 16){
8412     shCount -= 16;
8413     if(shCount)
8414       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8415     else{
8416       movLeft2Result(left, MSB24, result, LSB);
8417       movLeft2Result(left, MSB32, result, MSB16);
8418     }
8419     pic16_addSign(result, MSB24, sign);
8420   }
8421   else if(shCount >= 8){
8422     shCount -= 8;
8423     if(shCount == 1)
8424       shiftRLong(left, MSB16, result, sign);
8425     else if(shCount == 0){
8426       movLeft2Result(left, MSB16, result, LSB);
8427       movLeft2Result(left, MSB24, result, MSB16);
8428       movLeft2Result(left, MSB32, result, MSB24);
8429       pic16_addSign(result, MSB32, sign);
8430     }
8431     else{ //shcount >= 2
8432       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8433       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8434       /* the last shift is signed */
8435       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8436       pic16_addSign(result, MSB32, sign);
8437     }
8438   }
8439   else{   /* 1 <= shCount <= 7 */
8440     if(shCount <= 2){
8441       shiftRLong(left, LSB, result, sign);
8442       if(shCount == 2)
8443         shiftRLong(result, LSB, result, sign);
8444     }
8445     else{
8446       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8447       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8448       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8449     }
8450   }
8451 }
8452
8453 /*-----------------------------------------------------------------*/
8454 /* genRightShiftLiteral - right shifting by known count            */
8455 /*-----------------------------------------------------------------*/
8456 static void genRightShiftLiteral (operand *left,
8457                                   operand *right,
8458                                   operand *result,
8459                                   iCode *ic,
8460                                   int sign)
8461 {    
8462   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8463   int lsize,res_size;
8464
8465   pic16_freeAsmop(right,NULL,ic,TRUE);
8466
8467   pic16_aopOp(left,ic,FALSE);
8468   pic16_aopOp(result,ic,FALSE);
8469
8470   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8471
8472 #if VIEW_SIZE
8473   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8474                  AOP_SIZE(left));
8475 #endif
8476
8477   lsize = pic16_getDataSize(left);
8478   res_size = pic16_getDataSize(result);
8479   /* test the LEFT size !!! */
8480
8481   /* I suppose that the left size >= result size */
8482   if(shCount == 0){
8483     while(res_size--)
8484       movLeft2Result(left, lsize, result, res_size);
8485   }
8486
8487   else if(shCount >= (lsize * 8)){
8488
8489     if(res_size == 1) {
8490       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8491       if(sign) {
8492         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8493         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8494       }
8495     } else {
8496
8497       if(sign) {
8498         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8499         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8500         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8501         while(res_size--)
8502           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8503
8504       } else {
8505
8506         while(res_size--)
8507           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8508       }
8509     }
8510   } else {
8511
8512     switch (res_size) {
8513     case 1:
8514       genrshOne (result,left,shCount,sign);
8515       break;
8516
8517     case 2:
8518       genrshTwo (result,left,shCount,sign);
8519       break;
8520
8521     case 4:
8522       genrshFour (result,left,shCount,sign);
8523       break;
8524     default :
8525       break;
8526     }
8527
8528   }
8529
8530   pic16_freeAsmop(left,NULL,ic,TRUE);
8531   pic16_freeAsmop(result,NULL,ic,TRUE);
8532 }
8533
8534 /*-----------------------------------------------------------------*/
8535 /* genSignedRightShift - right shift of signed number              */
8536 /*-----------------------------------------------------------------*/
8537 static void genSignedRightShift (iCode *ic)
8538 {
8539   operand *right, *left, *result;
8540   int size, offset;
8541   //  char *l;
8542   symbol *tlbl, *tlbl1 ;
8543   pCodeOp *pctemp;
8544
8545   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8546
8547   /* we do it the hard way put the shift count in b
8548      and loop thru preserving the sign */
8549   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8550
8551   right = IC_RIGHT(ic);
8552   left  = IC_LEFT(ic);
8553   result = IC_RESULT(ic);
8554
8555   pic16_aopOp(right,ic,FALSE);  
8556   pic16_aopOp(left,ic,FALSE);
8557   pic16_aopOp(result,ic,FALSE);
8558
8559
8560   if ( AOP_TYPE(right) == AOP_LIT) {
8561     genRightShiftLiteral (left,right,result,ic,1);
8562     return ;
8563   }
8564   /* shift count is unknown then we have to form 
8565      a loop get the loop count in B : Note: we take
8566      only the lower order byte since shifting
8567      more that 32 bits make no sense anyway, ( the
8568      largest size of an object can be only 32 bits ) */  
8569
8570   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8571   //pic16_emitcode("inc","b");
8572   //pic16_freeAsmop (right,NULL,ic,TRUE);
8573   //pic16_aopOp(left,ic,FALSE);
8574   //pic16_aopOp(result,ic,FALSE);
8575
8576   /* now move the left to the result if they are not the
8577      same */
8578   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8579       AOP_SIZE(result) > 1) {
8580
8581     size = AOP_SIZE(result);
8582     offset=0;
8583     while (size--) { 
8584       /*
8585         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8586         if (*l == '@' && IS_AOP_PREG(result)) {
8587
8588         pic16_emitcode("mov","a,%s",l);
8589         pic16_aopPut(AOP(result),"a",offset);
8590         } else
8591         pic16_aopPut(AOP(result),l,offset);
8592       */
8593       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8594       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8595
8596       offset++;
8597     }
8598   }
8599
8600   /* mov the highest order bit to OVR */    
8601   tlbl = newiTempLabel(NULL);
8602   tlbl1= newiTempLabel(NULL);
8603
8604   size = AOP_SIZE(result);
8605   offset = size - 1;
8606
8607   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8608
8609   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8610
8611   /* offset should be 0, 1 or 3 */
8612   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8613   emitSKPNZ;
8614   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8615
8616   pic16_emitpcode(POC_MOVWF, pctemp);
8617
8618
8619   pic16_emitpLabel(tlbl->key);
8620
8621   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8622   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8623
8624   while(--size) {
8625     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8626   }
8627
8628   pic16_emitpcode(POC_DECFSZ,  pctemp);
8629   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8630   pic16_emitpLabel(tlbl1->key);
8631
8632   pic16_popReleaseTempReg(pctemp);
8633 #if 0
8634   size = AOP_SIZE(result);
8635   offset = size - 1;
8636   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8637   pic16_emitcode("rlc","a");
8638   pic16_emitcode("mov","ov,c");
8639   /* if it is only one byte then */
8640   if (size == 1) {
8641     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8642     MOVA(l);
8643     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8644     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8645     pic16_emitcode("mov","c,ov");
8646     pic16_emitcode("rrc","a");
8647     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8648     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8649     pic16_aopPut(AOP(result),"a",0);
8650     goto release ;
8651   }
8652
8653   reAdjustPreg(AOP(result));
8654   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8655   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8656   pic16_emitcode("mov","c,ov");
8657   while (size--) {
8658     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8659     MOVA(l);
8660     pic16_emitcode("rrc","a");         
8661     pic16_aopPut(AOP(result),"a",offset--);
8662   }
8663   reAdjustPreg(AOP(result));
8664   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8665   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8666
8667  release:
8668 #endif
8669
8670   pic16_freeAsmop(left,NULL,ic,TRUE);
8671   pic16_freeAsmop(result,NULL,ic,TRUE);
8672   pic16_freeAsmop(right,NULL,ic,TRUE);
8673 }
8674
8675 /*-----------------------------------------------------------------*/
8676 /* genRightShift - generate code for right shifting                */
8677 /*-----------------------------------------------------------------*/
8678 static void genRightShift (iCode *ic)
8679 {
8680     operand *right, *left, *result;
8681     sym_link *letype ;
8682     int size, offset;
8683     char *l;
8684     symbol *tlbl, *tlbl1 ;
8685
8686     /* if signed then we do it the hard way preserve the
8687     sign bit moving it inwards */
8688     letype = getSpec(operandType(IC_LEFT(ic)));
8689     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8690
8691     if (!SPEC_USIGN(letype)) {
8692         genSignedRightShift (ic);
8693         return ;
8694     }
8695
8696     /* signed & unsigned types are treated the same : i.e. the
8697     signed is NOT propagated inwards : quoting from the
8698     ANSI - standard : "for E1 >> E2, is equivalent to division
8699     by 2**E2 if unsigned or if it has a non-negative value,
8700     otherwise the result is implementation defined ", MY definition
8701     is that the sign does not get propagated */
8702
8703     right = IC_RIGHT(ic);
8704     left  = IC_LEFT(ic);
8705     result = IC_RESULT(ic);
8706
8707     pic16_aopOp(right,ic,FALSE);
8708
8709     /* if the shift count is known then do it 
8710     as efficiently as possible */
8711     if (AOP_TYPE(right) == AOP_LIT) {
8712         genRightShiftLiteral (left,right,result,ic, 0);
8713         return ;
8714     }
8715
8716     /* shift count is unknown then we have to form 
8717     a loop get the loop count in B : Note: we take
8718     only the lower order byte since shifting
8719     more that 32 bits make no sense anyway, ( the
8720     largest size of an object can be only 32 bits ) */  
8721
8722     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8723     pic16_emitcode("inc","b");
8724     pic16_aopOp(left,ic,FALSE);
8725     pic16_aopOp(result,ic,FALSE);
8726
8727     /* now move the left to the result if they are not the
8728     same */
8729     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8730         AOP_SIZE(result) > 1) {
8731
8732         size = AOP_SIZE(result);
8733         offset=0;
8734         while (size--) {
8735             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8736             if (*l == '@' && IS_AOP_PREG(result)) {
8737
8738                 pic16_emitcode("mov","a,%s",l);
8739                 pic16_aopPut(AOP(result),"a",offset);
8740             } else
8741                 pic16_aopPut(AOP(result),l,offset);
8742             offset++;
8743         }
8744     }
8745
8746     tlbl = newiTempLabel(NULL);
8747     tlbl1= newiTempLabel(NULL);
8748     size = AOP_SIZE(result);
8749     offset = size - 1;
8750
8751     /* if it is only one byte then */
8752     if (size == 1) {
8753
8754       tlbl = newiTempLabel(NULL);
8755       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8756         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8757         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8758       }
8759
8760       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8761       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8762       pic16_emitpLabel(tlbl->key);
8763       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8764       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8765       emitSKPC;
8766       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8767
8768       goto release ;
8769     }
8770
8771     reAdjustPreg(AOP(result));
8772     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8773     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8774     CLRC;
8775     while (size--) {
8776         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8777         MOVA(l);
8778         pic16_emitcode("rrc","a");         
8779         pic16_aopPut(AOP(result),"a",offset--);
8780     }
8781     reAdjustPreg(AOP(result));
8782
8783     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8784     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8785
8786 release:
8787     pic16_freeAsmop(left,NULL,ic,TRUE);
8788     pic16_freeAsmop (right,NULL,ic,TRUE);
8789     pic16_freeAsmop(result,NULL,ic,TRUE);
8790 }
8791
8792 /*-----------------------------------------------------------------*/
8793 /* genUnpackBits - generates code for unpacking bits               */
8794 /*-----------------------------------------------------------------*/
8795 static void genUnpackBits (operand *result, char *rname, int ptype)
8796 {    
8797     int shCnt ;
8798     int rlen = 0 ;
8799     sym_link *etype;
8800     int offset = 0 ;
8801
8802         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8803         etype = getSpec(operandType(result));
8804
8805         /* read the first byte  */
8806         switch (ptype) {
8807                 case POINTER:
8808                 case IPOINTER:
8809                 case PPOINTER:
8810                 case FPOINTER:
8811                 case GPOINTER:
8812                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8813                         break;
8814                 case CPOINTER:
8815                         pic16_emitcode("clr","a");
8816                         pic16_emitcode("movc","a","@a+dptr");
8817                         break;
8818         }
8819         
8820
8821         /* if we have bitdisplacement then it fits   */
8822         /* into this byte completely or if length is */
8823         /* less than a byte                          */
8824         if ((shCnt = SPEC_BSTR(etype)) || 
8825                 (SPEC_BLEN(etype) <= 8))  {
8826
8827                 /* shift right acc */
8828                 AccRsh(shCnt, 0);
8829
8830                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8831                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8832
8833 /* VR -- normally I would use the following, but since we use the hack,
8834  * to avoid the masking from AccRsh, why not mask it right now? */
8835
8836 /*
8837                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8838 */
8839
8840                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8841           return ;
8842         }
8843
8844
8845
8846         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8847         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8848         exit(-1);
8849
8850     /* bit field did not fit in a byte  */
8851     rlen = SPEC_BLEN(etype) - 8;
8852     pic16_aopPut(AOP(result),"a",offset++);
8853
8854     while (1)  {
8855
8856         switch (ptype) {
8857         case POINTER:
8858         case IPOINTER:
8859             pic16_emitcode("inc","%s",rname);
8860             pic16_emitcode("mov","a,@%s",rname);
8861             break;
8862             
8863         case PPOINTER:
8864             pic16_emitcode("inc","%s",rname);
8865             pic16_emitcode("movx","a,@%s",rname);
8866             break;
8867
8868         case FPOINTER:
8869             pic16_emitcode("inc","dptr");
8870             pic16_emitcode("movx","a,@dptr");
8871             break;
8872             
8873         case CPOINTER:
8874             pic16_emitcode("clr","a");
8875             pic16_emitcode("inc","dptr");
8876             pic16_emitcode("movc","a","@a+dptr");
8877             break;
8878             
8879         case GPOINTER:
8880             pic16_emitcode("inc","dptr");
8881             pic16_emitcode("lcall","__gptrget");
8882             break;
8883         }
8884
8885         rlen -= 8;            
8886         /* if we are done */
8887         if ( rlen <= 0 )
8888             break ;
8889         
8890         pic16_aopPut(AOP(result),"a",offset++);
8891                               
8892     }
8893     
8894     if (rlen) {
8895         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8896         pic16_aopPut(AOP(result),"a",offset);          
8897     }
8898     
8899     return ;
8900 }
8901
8902
8903 static void genDataPointerGet(operand *left,
8904                               operand *result,
8905                               iCode *ic)
8906 {
8907   int size, offset = 0, leoffset=0 ;
8908
8909         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8910         pic16_aopOp(result, ic, FALSE);
8911
8912         size = AOP_SIZE(result);
8913 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8914
8915
8916 #if 0
8917         /* The following tests may save a redudant movff instruction when
8918          * accessing unions */
8919          
8920         /* if they are the same */
8921         if (operandsEqu (left, result)) {
8922                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8923                 goto release;
8924         }
8925 #endif
8926
8927 #if 0
8928         /* if they are the same registers */
8929         if (pic16_sameRegs(AOP(left),AOP(result))) {
8930                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8931                 goto release;
8932         }
8933 #endif
8934
8935 #if 0
8936         if ( AOP_TYPE(left) == AOP_PCODE) {
8937                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
8938                                 AOP(left)->aopu.pcop->name,
8939                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
8940                                 PCOR(AOP(left)->aopu.pcop)->instance:
8941                                 PCOI(AOP(left)->aopu.pcop)->offset);
8942         }
8943 #endif
8944
8945         if(AOP(left)->aopu.pcop->type == PO_DIR)
8946                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8947
8948         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8949
8950         while (size--) {
8951                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8952                 
8953                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8954                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8955                         mov2w(AOP(left), offset); // patch 8
8956                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8957                 } else {
8958                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8959                                 pic16_popGet(AOP(left), offset), //patch 8
8960                                 pic16_popGet(AOP(result), offset)));
8961                 }
8962
8963                 offset++;
8964                 leoffset++;
8965         }
8966
8967 //release:
8968     pic16_freeAsmop(result,NULL,ic,TRUE);
8969 }
8970
8971 void pic16_loadFSR0(operand *op)
8972 {
8973         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8974 }
8975
8976
8977 /*-----------------------------------------------------------------*/
8978 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8979 /*-----------------------------------------------------------------*/
8980 static void genNearPointerGet (operand *left, 
8981                                operand *result, 
8982                                iCode *ic)
8983 {
8984     asmop *aop = NULL;
8985     //regs *preg = NULL ;
8986     sym_link *rtype, *retype;
8987     sym_link *ltype = operandType(left);    
8988
8989         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8990         rtype = operandType(result);
8991         retype= getSpec(rtype);
8992     
8993         pic16_aopOp(left,ic,FALSE);
8994
8995         pic16_DumpOp("(left)",left);
8996         pic16_DumpOp("(result)",result);
8997
8998         /* if left is rematerialisable and
8999          * result is not bit variable type and
9000          * the left is pointer to data space i.e
9001          * lower 128 bytes of space */
9002         if (AOP_TYPE(left) == AOP_PCODE
9003                 && !IS_BITFIELD(retype)
9004                 && DCL_TYPE(ltype) == POINTER) {
9005
9006                 genDataPointerGet (left,result,ic);
9007                 pic16_freeAsmop(left, NULL, ic, TRUE);
9008           return ;
9009         }
9010     
9011         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9012
9013         /* if the value is already in a pointer register
9014          * then don't need anything more */
9015         if (!AOP_INPREG(AOP(left))) {
9016                 /* otherwise get a free pointer register */
9017                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9018                 
9019                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9020                 if( (AOP_TYPE(left) == AOP_PCODE) 
9021                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9022                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9023                 {
9024                         pic16_loadFSR0( left );  // patch 10
9025                 } else {
9026                         // set up FSR0 with address from left
9027                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9028                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9029                 }
9030         }
9031 //       else
9032 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9033     
9034         pic16_aopOp (result,ic,FALSE);
9035     
9036       /* if bitfield then unpack the bits */
9037     if (IS_BITFIELD(retype)) 
9038         genUnpackBits (result, NULL, POINTER);
9039     else {
9040         /* we have can just get the values */
9041       int size = AOP_SIZE(result);
9042       int offset = 0;   
9043         
9044       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9045
9046
9047         /* fsr0 is loaded already -- VR */
9048 //      pic16_loadFSR0( left );
9049
9050 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9051 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9052       while(size--) {
9053
9054         if(size) {
9055                 pic16_emitpcode(POC_MOVFF,
9056                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9057                                 pic16_popGet(AOP(result), offset++)));
9058         } else {
9059                 pic16_emitpcode(POC_MOVFF,
9060                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9061                                 pic16_popGet(AOP(result), offset++)));
9062         }
9063       }
9064 #if 0
9065 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9066 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9067         if(size)
9068           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9069 #endif
9070 /*
9071         while (size--) {
9072             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9073
9074                 pic16_emitcode("mov","a,@%s",rname);
9075                 pic16_aopPut(AOP(result),"a",offset);
9076             } else {
9077                 sprintf(buffer,"@%s",rname);
9078                 pic16_aopPut(AOP(result),buffer,offset);
9079             }
9080             offset++ ;
9081             if (size)
9082                 pic16_emitcode("inc","%s",rname);
9083         }
9084 */
9085     }
9086
9087     /* now some housekeeping stuff */
9088     if (aop) {
9089         /* we had to allocate for this iCode */
9090     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9091         pic16_freeAsmop(NULL,aop,ic,TRUE);
9092     } else { 
9093         /* we did not allocate which means left
9094            already in a pointer register, then
9095            if size > 0 && this could be used again
9096            we have to point it back to where it 
9097            belongs */
9098     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9099         if (AOP_SIZE(result) > 1 &&
9100             !OP_SYMBOL(left)->remat &&
9101             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9102               ic->depth )) {
9103 //          int size = AOP_SIZE(result) - 1;
9104 //          while (size--)
9105 //              pic16_emitcode("dec","%s",rname);
9106         }
9107     }
9108
9109     /* done */
9110     pic16_freeAsmop(left,NULL,ic,TRUE);
9111     pic16_freeAsmop(result,NULL,ic,TRUE);
9112      
9113 }
9114
9115 /*-----------------------------------------------------------------*/
9116 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9117 /*-----------------------------------------------------------------*/
9118 static void genPagedPointerGet (operand *left, 
9119                                operand *result, 
9120                                iCode *ic)
9121 {
9122     asmop *aop = NULL;
9123     regs *preg = NULL ;
9124     char *rname ;
9125     sym_link *rtype, *retype;    
9126
9127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9128
9129     rtype = operandType(result);
9130     retype= getSpec(rtype);
9131     
9132     pic16_aopOp(left,ic,FALSE);
9133
9134   /* if the value is already in a pointer register
9135        then don't need anything more */
9136     if (!AOP_INPREG(AOP(left))) {
9137         /* otherwise get a free pointer register */
9138         aop = newAsmop(0);
9139         preg = getFreePtr(ic,&aop,FALSE);
9140         pic16_emitcode("mov","%s,%s",
9141                 preg->name,
9142                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9143         rname = preg->name ;
9144     } else
9145         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9146     
9147     pic16_freeAsmop(left,NULL,ic,TRUE);
9148     pic16_aopOp (result,ic,FALSE);
9149
9150     /* if bitfield then unpack the bits */
9151     if (IS_BITFIELD(retype)) 
9152         genUnpackBits (result,rname,PPOINTER);
9153     else {
9154         /* we have can just get the values */
9155         int size = AOP_SIZE(result);
9156         int offset = 0 ;        
9157         
9158         while (size--) {
9159             
9160             pic16_emitcode("movx","a,@%s",rname);
9161             pic16_aopPut(AOP(result),"a",offset);
9162             
9163             offset++ ;
9164             
9165             if (size)
9166                 pic16_emitcode("inc","%s",rname);
9167         }
9168     }
9169
9170     /* now some housekeeping stuff */
9171     if (aop) {
9172         /* we had to allocate for this iCode */
9173         pic16_freeAsmop(NULL,aop,ic,TRUE);
9174     } else { 
9175         /* we did not allocate which means left
9176            already in a pointer register, then
9177            if size > 0 && this could be used again
9178            we have to point it back to where it 
9179            belongs */
9180         if (AOP_SIZE(result) > 1 &&
9181             !OP_SYMBOL(left)->remat &&
9182             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9183               ic->depth )) {
9184             int size = AOP_SIZE(result) - 1;
9185             while (size--)
9186                 pic16_emitcode("dec","%s",rname);
9187         }
9188     }
9189
9190     /* done */
9191     pic16_freeAsmop(result,NULL,ic,TRUE);
9192     
9193         
9194 }
9195
9196 /*-----------------------------------------------------------------*/
9197 /* genFarPointerGet - gget value from far space                    */
9198 /*-----------------------------------------------------------------*/
9199 static void genFarPointerGet (operand *left,
9200                               operand *result, iCode *ic)
9201 {
9202     int size, offset ;
9203     sym_link *retype = getSpec(operandType(result));
9204
9205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9206
9207     pic16_aopOp(left,ic,FALSE);
9208
9209     /* if the operand is already in dptr 
9210     then we do nothing else we move the value to dptr */
9211     if (AOP_TYPE(left) != AOP_STR) {
9212         /* if this is remateriazable */
9213         if (AOP_TYPE(left) == AOP_IMMD)
9214             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9215         else { /* we need to get it byte by byte */
9216             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9217             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9218             if (options.model == MODEL_FLAT24)
9219             {
9220                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9221             }
9222         }
9223     }
9224     /* so dptr know contains the address */
9225     pic16_freeAsmop(left,NULL,ic,TRUE);
9226     pic16_aopOp(result,ic,FALSE);
9227
9228     /* if bit then unpack */
9229     if (IS_BITFIELD(retype)) 
9230         genUnpackBits(result,"dptr",FPOINTER);
9231     else {
9232         size = AOP_SIZE(result);
9233         offset = 0 ;
9234
9235         while (size--) {
9236             pic16_emitcode("movx","a,@dptr");
9237             pic16_aopPut(AOP(result),"a",offset++);
9238             if (size)
9239                 pic16_emitcode("inc","dptr");
9240         }
9241     }
9242
9243     pic16_freeAsmop(result,NULL,ic,TRUE);
9244 }
9245 #if 0
9246 /*-----------------------------------------------------------------*/
9247 /* genCodePointerGet - get value from code space                  */
9248 /*-----------------------------------------------------------------*/
9249 static void genCodePointerGet (operand *left,
9250                                 operand *result, iCode *ic)
9251 {
9252     int size, offset ;
9253     sym_link *retype = getSpec(operandType(result));
9254
9255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9256
9257     pic16_aopOp(left,ic,FALSE);
9258
9259     /* if the operand is already in dptr 
9260     then we do nothing else we move the value to dptr */
9261     if (AOP_TYPE(left) != AOP_STR) {
9262         /* if this is remateriazable */
9263         if (AOP_TYPE(left) == AOP_IMMD)
9264             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9265         else { /* we need to get it byte by byte */
9266             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9267             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9268             if (options.model == MODEL_FLAT24)
9269             {
9270                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9271             }
9272         }
9273     }
9274     /* so dptr know contains the address */
9275     pic16_freeAsmop(left,NULL,ic,TRUE);
9276     pic16_aopOp(result,ic,FALSE);
9277
9278     /* if bit then unpack */
9279     if (IS_BITFIELD(retype)) 
9280         genUnpackBits(result,"dptr",CPOINTER);
9281     else {
9282         size = AOP_SIZE(result);
9283         offset = 0 ;
9284
9285         while (size--) {
9286             pic16_emitcode("clr","a");
9287             pic16_emitcode("movc","a,@a+dptr");
9288             pic16_aopPut(AOP(result),"a",offset++);
9289             if (size)
9290                 pic16_emitcode("inc","dptr");
9291         }
9292     }
9293
9294     pic16_freeAsmop(result,NULL,ic,TRUE);
9295 }
9296 #endif
9297 /*-----------------------------------------------------------------*/
9298 /* genGenPointerGet - gget value from generic pointer space        */
9299 /*-----------------------------------------------------------------*/
9300 static void genGenPointerGet (operand *left,
9301                               operand *result, iCode *ic)
9302 {
9303   int size, offset, lit;
9304   sym_link *retype = getSpec(operandType(result));
9305
9306         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9307         pic16_aopOp(left,ic,FALSE);
9308         pic16_aopOp(result,ic,FALSE);
9309         size = AOP_SIZE(result);
9310
9311         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9312
9313         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9314
9315                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9316                 // load FSR0 from immediate
9317                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9318
9319 //              pic16_loadFSR0( left );
9320
9321                 offset = 0;
9322                 while(size--) {
9323                         if(size) {
9324                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9325                         } else {
9326                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9327                         }
9328                         offset++;
9329                 }
9330                 goto release;
9331
9332         }
9333         else { /* we need to get it byte by byte */
9334                 // set up FSR0 with address from left
9335                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9336                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9337
9338                 offset = 0 ;
9339
9340                 while(size--) {
9341                         if(size) {
9342                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9343                         } else {
9344                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9345                         }
9346                         offset++;
9347                 }
9348                 goto release;
9349         }
9350
9351   /* if bit then unpack */
9352         if (IS_BITFIELD(retype)) 
9353                 genUnpackBits(result,"BAD",GPOINTER);
9354
9355         release:
9356         pic16_freeAsmop(left,NULL,ic,TRUE);
9357         pic16_freeAsmop(result,NULL,ic,TRUE);
9358
9359 }
9360
9361 /*-----------------------------------------------------------------*/
9362 /* genConstPointerGet - get value from const generic pointer space */
9363 /*-----------------------------------------------------------------*/
9364 static void genConstPointerGet (operand *left,
9365                                 operand *result, iCode *ic)
9366 {
9367   //sym_link *retype = getSpec(operandType(result));
9368   // symbol *albl = newiTempLabel(NULL);        // patch 15
9369   // symbol *blbl = newiTempLabel(NULL);        //
9370   // PIC_OPCODE poc;                            // patch 15
9371   int size;
9372   int offset = 0;
9373
9374   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9375   pic16_aopOp(left,ic,FALSE);
9376   pic16_aopOp(result,ic,TRUE);
9377   size = AOP_SIZE(result);
9378
9379   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9380
9381   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9382 #if 0                                                                   // patch 15
9383   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9384   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9385   pic16_emitpLabel(albl->key);
9386
9387   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9388     
9389   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9390   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9391   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9392   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9393   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9394
9395   pic16_emitpLabel(blbl->key);
9396
9397   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9398 #endif                                                                  // patch 15
9399
9400
9401   // set up table pointer
9402   if( (AOP_TYPE(left) == AOP_PCODE) 
9403       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9404           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9405     {
9406       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9407       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9408       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9409       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9410       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9411       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9412     }
9413   else
9414     {
9415       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9416       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9417       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9418     }
9419
9420
9421   while(size--)
9422     {
9423       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9424       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9425       offset++;
9426     }
9427                                                                         // .... patch 15
9428   pic16_freeAsmop(left,NULL,ic,TRUE);
9429   pic16_freeAsmop(result,NULL,ic,TRUE);
9430
9431 }
9432 /*-----------------------------------------------------------------*/
9433 /* genPointerGet - generate code for pointer get                   */
9434 /*-----------------------------------------------------------------*/
9435 static void genPointerGet (iCode *ic)
9436 {
9437     operand *left, *result ;
9438     sym_link *type, *etype;
9439     int p_type;
9440
9441     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9442
9443     left = IC_LEFT(ic);
9444     result = IC_RESULT(ic) ;
9445
9446     /* depending on the type of pointer we need to
9447     move it to the correct pointer register */
9448     type = operandType(left);
9449     etype = getSpec(type);
9450
9451 #if 0
9452     if (IS_PTR_CONST(type))
9453 #else
9454     if (IS_CODEPTR(type))
9455 #endif
9456       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9457
9458     /* if left is of type of pointer then it is simple */
9459     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9460         p_type = DCL_TYPE(type);
9461     else {
9462         /* we have to go by the storage class */
9463         p_type = PTR_TYPE(SPEC_OCLS(etype));
9464
9465         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9466
9467         if (SPEC_OCLS(etype)->codesp ) {
9468           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9469           //p_type = CPOINTER ; 
9470         }
9471         else
9472             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9473               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9474                /*p_type = FPOINTER ;*/ 
9475             else
9476                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9477                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9478 /*                  p_type = PPOINTER; */
9479                 else
9480                     if (SPEC_OCLS(etype) == idata )
9481                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9482 /*                      p_type = IPOINTER; */
9483                     else
9484                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9485 /*                      p_type = POINTER ; */
9486     }
9487
9488     /* now that we have the pointer type we assign
9489     the pointer values */
9490     switch (p_type) {
9491
9492     case POINTER:       
9493     case IPOINTER:
9494         genNearPointerGet (left,result,ic);
9495         break;
9496
9497     case PPOINTER:
9498         genPagedPointerGet(left,result,ic);
9499         break;
9500
9501     case FPOINTER:
9502         genFarPointerGet (left,result,ic);
9503         break;
9504
9505     case CPOINTER:
9506         genConstPointerGet (left,result,ic);
9507         //pic16_emitcodePointerGet (left,result,ic);
9508         break;
9509
9510     case GPOINTER:
9511 #if 0
9512       if (IS_PTR_CONST(type))
9513         genConstPointerGet (left,result,ic);
9514       else
9515 #endif
9516         genGenPointerGet (left,result,ic);
9517       break;
9518     }
9519
9520 }
9521
9522 /*-----------------------------------------------------------------*/
9523 /* genPackBits - generates code for packed bit storage             */
9524 /*-----------------------------------------------------------------*/
9525 static void genPackBits (sym_link    *etype ,
9526                          operand *right ,
9527                          char *rname, int p_type)
9528 {
9529   int shCnt = 0 ;
9530   int offset = 0  ;
9531   int rLen = 0 ;
9532   int blen, bstr ;   
9533   char *l ;
9534
9535         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9536         blen = SPEC_BLEN(etype);
9537         bstr = SPEC_BSTR(etype);
9538
9539         if(AOP_TYPE(right) == AOP_LIT) {
9540                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9541                 offset++;
9542         } else
9543                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9544
9545 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9546         MOVA(l);   
9547 */
9548         /* if the bit lenth is less than or    */
9549         /* it exactly fits a byte then         */
9550         if((shCnt=SPEC_BSTR(etype))
9551                 || SPEC_BLEN(etype) <= 8 )  {
9552
9553                 /* shift left acc */
9554                 AccLsh(shCnt);
9555
9556                 /* using PRODL as a temporary register here */
9557                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9558
9559                 switch (p_type) {
9560                         case FPOINTER:
9561                         case POINTER:
9562                         case GPOINTER:
9563                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9564 //                              pic16_emitcode ("mov","b,a");
9565 //                              pic16_emitcode("mov","a,@%s",rname);
9566                                 break;
9567                 }
9568 #if 1
9569                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9570                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9571                                         (unsigned char)(0xff >> (8-bstr))) ));
9572                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9573                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9574 #endif
9575
9576 #if 0
9577                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9578                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9579                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9580                 pic16_emitcode ("orl","a,b");
9581                 if (p_type == GPOINTER)
9582                         pic16_emitcode("pop","b");
9583
9584                 
9585                 switch (p_type) {
9586                         case POINTER:
9587                                 pic16_emitcode("mov","@%s,a",rname);
9588                                 break;
9589                         case FPOINTER:
9590                                 pic16_emitcode("movx","@dptr,a");
9591                                 break;
9592                         case GPOINTER:
9593                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9594                                 break;
9595                 }
9596 #endif
9597
9598           return;
9599         }
9600
9601
9602         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9603         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9604         exit(-1);
9605
9606
9607     /* if we r done */
9608     if ( SPEC_BLEN(etype) <= 8 )
9609         return ;
9610
9611     pic16_emitcode("inc","%s",rname);
9612     rLen = SPEC_BLEN(etype) ;     
9613
9614
9615
9616     /* now generate for lengths greater than one byte */
9617     while (1) {
9618
9619         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9620
9621         rLen -= 8 ;
9622         if (rLen <= 0 )
9623             break ;
9624
9625         switch (p_type) {
9626             case POINTER:
9627                 if (*l == '@') {
9628                     MOVA(l);
9629                     pic16_emitcode("mov","@%s,a",rname);
9630                 } else
9631                     pic16_emitcode("mov","@%s,%s",rname,l);
9632                 break;
9633
9634             case FPOINTER:
9635                 MOVA(l);
9636                 pic16_emitcode("movx","@dptr,a");
9637                 break;
9638
9639             case GPOINTER:
9640                 MOVA(l);
9641                 DEBUGpic16_emitcode(";lcall","__gptrput");
9642                 break;  
9643         }   
9644         pic16_emitcode ("inc","%s",rname);
9645     }
9646
9647     MOVA(l);
9648
9649     /* last last was not complete */
9650     if (rLen)   {
9651         /* save the byte & read byte */
9652         switch (p_type) {
9653             case POINTER:
9654                 pic16_emitcode ("mov","b,a");
9655                 pic16_emitcode("mov","a,@%s",rname);
9656                 break;
9657
9658             case FPOINTER:
9659                 pic16_emitcode ("mov","b,a");
9660                 pic16_emitcode("movx","a,@dptr");
9661                 break;
9662
9663             case GPOINTER:
9664                 pic16_emitcode ("push","b");
9665                 pic16_emitcode ("push","acc");
9666                 pic16_emitcode ("lcall","__gptrget");
9667                 pic16_emitcode ("pop","b");
9668                 break;
9669         }
9670
9671         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9672         pic16_emitcode ("orl","a,b");
9673     }
9674
9675     if (p_type == GPOINTER)
9676         pic16_emitcode("pop","b");
9677
9678     switch (p_type) {
9679
9680     case POINTER:
9681         pic16_emitcode("mov","@%s,a",rname);
9682         break;
9683         
9684     case FPOINTER:
9685         pic16_emitcode("movx","@dptr,a");
9686         break;
9687         
9688     case GPOINTER:
9689         DEBUGpic16_emitcode(";lcall","__gptrput");
9690         break;                  
9691     }
9692 }
9693 /*-----------------------------------------------------------------*/
9694 /* genDataPointerSet - remat pointer to data space                 */
9695 /*-----------------------------------------------------------------*/
9696 static void genDataPointerSet(operand *right,
9697                               operand *result,
9698                               iCode *ic)
9699 {
9700     int size, offset = 0, resoffset=0 ;
9701
9702     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9703     pic16_aopOp(right,ic,FALSE);
9704
9705     size = AOP_SIZE(right);
9706
9707 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9708
9709 #if 0
9710     if ( AOP_TYPE(result) == AOP_PCODE) {
9711       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9712               AOP(result)->aopu.pcop->name,
9713                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9714               PCOR(AOP(result)->aopu.pcop)->instance:
9715               PCOI(AOP(result)->aopu.pcop)->offset);
9716     }
9717 #endif
9718
9719         if(AOP(result)->aopu.pcop->type == PO_DIR)
9720                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9721
9722         while (size--) {
9723                 if (AOP_TYPE(right) == AOP_LIT) {
9724                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9725
9726                         lit = lit >> (8*offset);
9727                         if(lit&0xff) {
9728                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9729                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9730                         } else {
9731                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9732                         }
9733                 } else {
9734                         mov2w(AOP(right), offset);
9735                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9736                 }
9737                 offset++;
9738                 resoffset++;
9739         }
9740
9741     pic16_freeAsmop(right,NULL,ic,TRUE);
9742 }
9743
9744
9745
9746 /*-----------------------------------------------------------------*/
9747 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9748 /*-----------------------------------------------------------------*/
9749 static void genNearPointerSet (operand *right,
9750                                operand *result, 
9751                                iCode *ic)
9752 {
9753   asmop *aop = NULL;
9754   char *l;
9755   sym_link *retype;
9756   sym_link *ptype = operandType(result);
9757   sym_link *resetype;
9758     
9759         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9760         retype= getSpec(operandType(right));
9761         resetype = getSpec(operandType(result));
9762   
9763         pic16_aopOp(result,ic,FALSE);
9764     
9765         /* if the result is rematerializable &
9766          * in data space & not a bit variable */
9767         
9768         /* and result is not a bit variable */
9769         if (AOP_TYPE(result) == AOP_PCODE
9770 //              && AOP_TYPE(result) == AOP_IMMD
9771                 && DCL_TYPE(ptype) == POINTER
9772                 && !IS_BITFIELD(retype)
9773                 && !IS_BITFIELD(resetype)) {
9774
9775                 genDataPointerSet (right,result,ic);
9776                 pic16_freeAsmop(result,NULL,ic,TRUE);
9777           return;
9778         }
9779
9780         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9781         pic16_aopOp(right,ic,FALSE);
9782         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9783
9784         /* if the value is already in a pointer register
9785          * then don't need anything more */
9786         if (!AOP_INPREG(AOP(result))) {
9787                 /* otherwise get a free pointer register */
9788                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9789
9790                 if( (AOP_TYPE(result) == AOP_PCODE) 
9791                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9792                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9793                 {
9794                         pic16_loadFSR0( result );  // patch 10
9795                 } else {
9796                         // set up FSR0 with address of result
9797                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9798                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9799                 }
9800
9801         }
9802 //      else
9803 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9804
9805         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9806
9807         /* if bitfield then unpack the bits */
9808         if (IS_BITFIELD(resetype)) {
9809                 genPackBits (resetype, right, NULL, POINTER);
9810         } else {
9811                 /* we have can just get the values */
9812           int size = AOP_SIZE(right);
9813           int offset = 0 ;    
9814
9815                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9816                 while (size--) {
9817                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9818                         if (*l == '@' ) {
9819                                 //MOVA(l);
9820                                 //pic16_emitcode("mov","@%s,a",rname);
9821                                 pic16_emitcode("movf","indf0,w ;1");
9822                         } else {
9823
9824                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9825                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9826                                         if (size) {                                                                     // 
9827                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9828                                         } else {                                                                        // 
9829                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9830                                         }                                                                               // 
9831                                 } else { // no literal                                                                  // 
9832                                         if(size) {                                                                      // 
9833                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9834                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9835                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9836                                         } else {                                                                        // 
9837                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9838                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9839                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9840                                         }                                                                               //
9841                                 }                                                                                       // patch 10
9842                         }
9843                         offset++;
9844                 }
9845         }
9846
9847         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9848         /* now some housekeeping stuff */
9849         if (aop) {
9850                 /* we had to allocate for this iCode */
9851                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9852         } else { 
9853                 /* we did not allocate which means left
9854                  * already in a pointer register, then
9855                  * if size > 0 && this could be used again
9856                  * we have to point it back to where it 
9857                  * belongs */
9858                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9859                 if (AOP_SIZE(right) > 1
9860                         && !OP_SYMBOL(result)->remat
9861                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9862                                 || ic->depth )) {
9863
9864                   int size = AOP_SIZE(right) - 1;
9865
9866                         while (size--)
9867                                 pic16_emitcode("decf","fsr0,f");
9868                         //pic16_emitcode("dec","%s",rname);
9869                 }
9870         }
9871
9872         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9873         /* done */
9874 //release:
9875         pic16_freeAsmop(right,NULL,ic,TRUE);
9876         pic16_freeAsmop(result,NULL,ic,TRUE);
9877 }
9878
9879 /*-----------------------------------------------------------------*/
9880 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9881 /*-----------------------------------------------------------------*/
9882 static void genPagedPointerSet (operand *right,
9883                                operand *result, 
9884                                iCode *ic)
9885 {
9886     asmop *aop = NULL;
9887     regs *preg = NULL ;
9888     char *rname , *l;
9889     sym_link *retype;
9890        
9891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9892
9893     retype= getSpec(operandType(right));
9894     
9895     pic16_aopOp(result,ic,FALSE);
9896     
9897     /* if the value is already in a pointer register
9898        then don't need anything more */
9899     if (!AOP_INPREG(AOP(result))) {
9900         /* otherwise get a free pointer register */
9901         aop = newAsmop(0);
9902         preg = getFreePtr(ic,&aop,FALSE);
9903         pic16_emitcode("mov","%s,%s",
9904                 preg->name,
9905                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9906         rname = preg->name ;
9907     } else
9908         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9909     
9910     pic16_freeAsmop(result,NULL,ic,TRUE);
9911     pic16_aopOp (right,ic,FALSE);
9912
9913     /* if bitfield then unpack the bits */
9914     if (IS_BITFIELD(retype)) 
9915         genPackBits (retype,right,rname,PPOINTER);
9916     else {
9917         /* we have can just get the values */
9918         int size = AOP_SIZE(right);
9919         int offset = 0 ;        
9920         
9921         while (size--) {
9922             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9923             
9924             MOVA(l);
9925             pic16_emitcode("movx","@%s,a",rname);
9926
9927             if (size)
9928                 pic16_emitcode("inc","%s",rname);
9929
9930             offset++;
9931         }
9932     }
9933     
9934     /* now some housekeeping stuff */
9935     if (aop) {
9936         /* we had to allocate for this iCode */
9937         pic16_freeAsmop(NULL,aop,ic,TRUE);
9938     } else { 
9939         /* we did not allocate which means left
9940            already in a pointer register, then
9941            if size > 0 && this could be used again
9942            we have to point it back to where it 
9943            belongs */
9944         if (AOP_SIZE(right) > 1 &&
9945             !OP_SYMBOL(result)->remat &&
9946             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9947               ic->depth )) {
9948             int size = AOP_SIZE(right) - 1;
9949             while (size--)
9950                 pic16_emitcode("dec","%s",rname);
9951         }
9952     }
9953
9954     /* done */
9955     pic16_freeAsmop(right,NULL,ic,TRUE);
9956     
9957         
9958 }
9959
9960 /*-----------------------------------------------------------------*/
9961 /* genFarPointerSet - set value from far space                     */
9962 /*-----------------------------------------------------------------*/
9963 static void genFarPointerSet (operand *right,
9964                               operand *result, iCode *ic)
9965 {
9966     int size, offset ;
9967     sym_link *retype = getSpec(operandType(right));
9968
9969     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9970     pic16_aopOp(result,ic,FALSE);
9971
9972     /* if the operand is already in dptr 
9973     then we do nothing else we move the value to dptr */
9974     if (AOP_TYPE(result) != AOP_STR) {
9975         /* if this is remateriazable */
9976         if (AOP_TYPE(result) == AOP_IMMD)
9977             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9978         else { /* we need to get it byte by byte */
9979             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9980             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9981             if (options.model == MODEL_FLAT24)
9982             {
9983                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9984             }
9985         }
9986     }
9987     /* so dptr know contains the address */
9988     pic16_freeAsmop(result,NULL,ic,TRUE);
9989     pic16_aopOp(right,ic,FALSE);
9990
9991     /* if bit then unpack */
9992     if (IS_BITFIELD(retype)) 
9993         genPackBits(retype,right,"dptr",FPOINTER);
9994     else {
9995         size = AOP_SIZE(right);
9996         offset = 0 ;
9997
9998         while (size--) {
9999             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10000             MOVA(l);
10001             pic16_emitcode("movx","@dptr,a");
10002             if (size)
10003                 pic16_emitcode("inc","dptr");
10004         }
10005     }
10006
10007     pic16_freeAsmop(right,NULL,ic,TRUE);
10008 }
10009
10010 /*-----------------------------------------------------------------*/
10011 /* genGenPointerSet - set value from generic pointer space         */
10012 /*-----------------------------------------------------------------*/
10013 static void genGenPointerSet (operand *right,
10014                               operand *result, iCode *ic)
10015 {
10016         int i, size, offset, lit;
10017         sym_link *retype = getSpec(operandType(right));
10018
10019         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10020
10021         pic16_aopOp(result,ic,FALSE);
10022         pic16_aopOp(right,ic,FALSE);
10023         size = AOP_SIZE(right);
10024         offset = 0;
10025
10026         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10027
10028         /* if the operand is already in dptr 
10029                 then we do nothing else we move the value to dptr */
10030         if (AOP_TYPE(result) != AOP_STR) {
10031                 /* if this is remateriazable */
10032                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10033                 // WARNING: anythig until "else" is untested!
10034                 if (AOP_TYPE(result) == AOP_IMMD) {
10035                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10036                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10037                         // load FSR0 from immediate
10038                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10039                         offset = 0;
10040                         while(size--) {
10041                                 if(size) {
10042                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10043                                 } else {
10044                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10045                                 }
10046                                 offset++;
10047                         }
10048                         goto release;
10049                 }
10050                 else { /* we need to get it byte by byte */
10051                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10052                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10053
10054                         // set up FSR0 with address of result
10055                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10056                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10057
10058                         /* hack hack! see if this the FSR. If so don't load W */
10059                         if(AOP_TYPE(right) != AOP_ACC) {
10060
10061                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10062
10063                                 if(AOP_TYPE(right) == AOP_LIT)
10064                                 {
10065                                         // copy literal
10066                                         // note: pic16_popGet handles sign extension
10067                                         for(i=0;i<size;i++) {
10068                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10069                                                 if(i < size-1)
10070                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10071                                                 else
10072                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10073                                         }
10074                                 } else {
10075                                         // copy regs
10076
10077                                         for(i=0;i<size;i++) {
10078                                                 if(i < size-1)
10079                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10080                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10081                                                 else
10082                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10083                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10084                                         }
10085                                 }
10086                                 goto release;
10087                         } 
10088                         // right = ACC
10089                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10090                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10091                         goto release;
10092         } // if (AOP_TYPE(result) != AOP_IMMD)
10093
10094         } // if (AOP_TYPE(result) != AOP_STR)
10095         /* so dptr know contains the address */
10096
10097
10098         /* if bit then unpack */
10099         if (IS_BITFIELD(retype)) 
10100                 genPackBits(retype,right,"dptr",GPOINTER);
10101         else {
10102                 size = AOP_SIZE(right);
10103                 offset = 0 ;
10104
10105                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10106
10107                 // set up FSR0 with address of result
10108                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10109                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10110         
10111                 while (size--) {
10112                         if (AOP_TYPE(right) == AOP_LIT) {
10113                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10114                                 if (size) {
10115                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10116                                 } else {
10117                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10118                                 }
10119                         } else { // no literal
10120                                 if(size) {
10121                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10122                                 } else {
10123                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10124                                 }
10125                         }
10126                         offset++;
10127                 }
10128         }
10129
10130         release:
10131         pic16_freeAsmop(right,NULL,ic,TRUE);
10132         pic16_freeAsmop(result,NULL,ic,TRUE);
10133 }
10134
10135 /*-----------------------------------------------------------------*/
10136 /* genPointerSet - stores the value into a pointer location        */
10137 /*-----------------------------------------------------------------*/
10138 static void genPointerSet (iCode *ic)
10139 {    
10140     operand *right, *result ;
10141     sym_link *type, *etype;
10142     int p_type;
10143
10144     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10145
10146     right = IC_RIGHT(ic);
10147     result = IC_RESULT(ic) ;
10148
10149     /* depending on the type of pointer we need to
10150     move it to the correct pointer register */
10151     type = operandType(result);
10152     etype = getSpec(type);
10153     /* if left is of type of pointer then it is simple */
10154     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10155         p_type = DCL_TYPE(type);
10156     }
10157     else {
10158         /* we have to go by the storage class */
10159         p_type = PTR_TYPE(SPEC_OCLS(etype));
10160
10161 /*      if (SPEC_OCLS(etype)->codesp ) { */
10162 /*          p_type = CPOINTER ;  */
10163 /*      } */
10164 /*      else */
10165 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10166 /*              p_type = FPOINTER ; */
10167 /*          else */
10168 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10169 /*                  p_type = PPOINTER ; */
10170 /*              else */
10171 /*                  if (SPEC_OCLS(etype) == idata ) */
10172 /*                      p_type = IPOINTER ; */
10173 /*                  else */
10174 /*                      p_type = POINTER ; */
10175     }
10176
10177     /* now that we have the pointer type we assign
10178     the pointer values */
10179     switch (p_type) {
10180
10181     case POINTER:
10182     case IPOINTER:
10183         genNearPointerSet (right,result,ic);
10184         break;
10185
10186     case PPOINTER:
10187         genPagedPointerSet (right,result,ic);
10188         break;
10189
10190     case FPOINTER:
10191         genFarPointerSet (right,result,ic);
10192         break;
10193
10194     case GPOINTER:
10195         genGenPointerSet (right,result,ic);
10196         break;
10197
10198     default:
10199       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10200               "genPointerSet: illegal pointer type");
10201     }
10202 }
10203
10204 /*-----------------------------------------------------------------*/
10205 /* genIfx - generate code for Ifx statement                        */
10206 /*-----------------------------------------------------------------*/
10207 static void genIfx (iCode *ic, iCode *popIc)
10208 {
10209   operand *cond = IC_COND(ic);
10210   int isbit =0;
10211
10212   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10213
10214   pic16_aopOp(cond,ic,FALSE);
10215
10216   /* get the value into acc */
10217   if (AOP_TYPE(cond) != AOP_CRY)
10218     pic16_toBoolean(cond);
10219   else
10220     isbit = 1;
10221   /* the result is now in the accumulator */
10222   pic16_freeAsmop(cond,NULL,ic,TRUE);
10223
10224   /* if there was something to be popped then do it */
10225   if (popIc)
10226     genIpop(popIc);
10227
10228   /* if the condition is  a bit variable */
10229   if (isbit && IS_ITEMP(cond) && 
10230       SPIL_LOC(cond)) {
10231     genIfxJump(ic,SPIL_LOC(cond)->rname);
10232     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10233   }
10234   else {
10235     if (isbit && !IS_ITEMP(cond))
10236       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10237     else
10238       genIfxJump(ic,"a");
10239   }
10240   ic->generated = 1;
10241
10242 }
10243
10244 /*-----------------------------------------------------------------*/
10245 /* genAddrOf - generates code for address of                       */
10246 /*-----------------------------------------------------------------*/
10247 static void genAddrOf (iCode *ic)
10248 {
10249   operand *result, *left;
10250   int size;
10251   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10252   pCodeOp *pcop0, *pcop1, *pcop2;
10253
10254         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10255
10256         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10257         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10258
10259         sym = OP_SYMBOL( left );
10260
10261         size = AOP_SIZE(IC_RESULT(ic));
10262
10263         if(pic16_debug_verbose) {
10264                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10265                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10266         }
10267         
10268         /* Assume that what we want the address of is in data space
10269          * since there is no stack on the PIC, yet! -- VR */
10270         /* low */
10271         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10272
10273         /* high */
10274         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10275         
10276         /* upper */
10277         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10278         
10279
10280         if (size == 3) {
10281                 pic16_emitpcode(POC_MOVLW, pcop0);
10282                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10283                 pic16_emitpcode(POC_MOVLW, pcop1);
10284                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10285                 pic16_emitpcode(POC_MOVLW, pcop2);
10286                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10287         } else
10288         if (size == 2) {
10289                 pic16_emitpcode(POC_MOVLW, pcop0);
10290                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10291                 pic16_emitpcode(POC_MOVLW, pcop1);
10292                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10293         } else {
10294                 pic16_emitpcode(POC_MOVLW, pcop0);
10295                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10296         }
10297
10298         pic16_freeAsmop(result,NULL,ic,TRUE);
10299         pic16_freeAsmop(left, NULL, ic, FALSE);
10300 }
10301
10302
10303 #if 0
10304 /*-----------------------------------------------------------------*/
10305 /* genFarFarAssign - assignment when both are in far space         */
10306 /*-----------------------------------------------------------------*/
10307 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10308 {
10309     int size = AOP_SIZE(right);
10310     int offset = 0;
10311     char *l ;
10312     /* first push the right side on to the stack */
10313     while (size--) {
10314         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10315         MOVA(l);
10316         pic16_emitcode ("push","acc");
10317     }
10318     
10319     pic16_freeAsmop(right,NULL,ic,FALSE);
10320     /* now assign DPTR to result */
10321     pic16_aopOp(result,ic,FALSE);
10322     size = AOP_SIZE(result);
10323     while (size--) {
10324         pic16_emitcode ("pop","acc");
10325         pic16_aopPut(AOP(result),"a",--offset);
10326     }
10327     pic16_freeAsmop(result,NULL,ic,FALSE);
10328         
10329 }
10330 #endif
10331
10332 /*-----------------------------------------------------------------*/
10333 /* genAssign - generate code for assignment                        */
10334 /*-----------------------------------------------------------------*/
10335 static void genAssign (iCode *ic)
10336 {
10337   operand *result, *right;
10338   int size, offset,know_W;
10339   unsigned long lit = 0L;
10340
10341   result = IC_RESULT(ic);
10342   right  = IC_RIGHT(ic) ;
10343
10344   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10345   
10346   /* if they are the same */
10347   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10348     return ;
10349
10350   pic16_aopOp(right,ic,FALSE);
10351   pic16_aopOp(result,ic,TRUE);
10352
10353   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10354
10355   /* if they are the same registers */
10356   if (pic16_sameRegs(AOP(right),AOP(result)))
10357     goto release;
10358
10359   /* if the result is a bit */
10360   if (AOP_TYPE(result) == AOP_CRY) {
10361     /* if the right size is a literal then
10362        we know what the value is */
10363     if (AOP_TYPE(right) == AOP_LIT) {
10364           
10365       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10366                   pic16_popGet(AOP(result),0));
10367
10368       if (((int) operandLitValue(right))) 
10369         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10370                        AOP(result)->aopu.aop_dir,
10371                        AOP(result)->aopu.aop_dir);
10372       else
10373         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10374                        AOP(result)->aopu.aop_dir,
10375                        AOP(result)->aopu.aop_dir);
10376       goto release;
10377     }
10378
10379     /* the right is also a bit variable */
10380     if (AOP_TYPE(right) == AOP_CRY) {
10381       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10382       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10383       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10384
10385       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10386                      AOP(result)->aopu.aop_dir,
10387                      AOP(result)->aopu.aop_dir);
10388       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10389                      AOP(right)->aopu.aop_dir,
10390                      AOP(right)->aopu.aop_dir);
10391       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10392                      AOP(result)->aopu.aop_dir,
10393                      AOP(result)->aopu.aop_dir);
10394       goto release ;
10395     }
10396
10397     /* we need to or */
10398     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10399     pic16_toBoolean(right);
10400     emitSKPZ;
10401     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10402     //pic16_aopPut(AOP(result),"a",0);
10403     goto release ;
10404   }
10405
10406   /* bit variables done */
10407   /* general case */
10408   size = AOP_SIZE(result);
10409   offset = 0 ;
10410   if(AOP_TYPE(right) == AOP_LIT)
10411     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10412
10413 /* VR - What is this?! */
10414   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10415   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10416     if(aopIdx(AOP(result),0) == 4) {
10417   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10418       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10419       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10420       goto release;
10421     } else
10422       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10423   }
10424
10425   know_W=-1;
10426   while (size--) {
10427   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10428     if(AOP_TYPE(right) == AOP_LIT) {
10429       if(lit&0xff) {
10430         if(know_W != (lit&0xff))
10431           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10432         know_W = lit&0xff;
10433         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10434       } else
10435         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10436
10437       lit >>= 8;
10438
10439     } else if (AOP_TYPE(right) == AOP_CRY) {
10440       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10441       if(offset == 0) {
10442         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10443         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10444       }
10445     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10446         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10447         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10448     } else {
10449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10450
10451 #if 1
10452         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10453            normally should work, but mind that the W register live range
10454            is not checked, so if the code generator assumes that the W
10455            is already loaded after such a pair, wrong code will be generated.
10456            
10457            Checking the live range is the next step.
10458            This is experimental code yet and has not been fully tested yet.
10459            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10460            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10461            
10462         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10463 #else   
10464         /* This is the old code, which is assumed(?!) that works fine(!?) */
10465
10466         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10467         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10468 #endif
10469     }
10470             
10471     offset++;
10472   }
10473
10474     
10475  release:
10476   pic16_freeAsmop (right,NULL,ic,FALSE);
10477   pic16_freeAsmop (result,NULL,ic,TRUE);
10478 }   
10479
10480 /*-----------------------------------------------------------------*/
10481 /* genJumpTab - generates code for jump table                       */
10482 /*-----------------------------------------------------------------*/
10483 static void genJumpTab (iCode *ic)
10484 {
10485     symbol *jtab;
10486     char *l;
10487
10488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10489
10490     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10491     /* get the condition into accumulator */
10492     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10493     MOVA(l);
10494     /* multiply by three */
10495     pic16_emitcode("add","a,acc");
10496     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10497
10498     jtab = newiTempLabel(NULL);
10499     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10500     pic16_emitcode("jmp","@a+dptr");
10501     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10502
10503     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10504     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10505     emitSKPNC;
10506     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10507     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10508     pic16_emitpLabel(jtab->key);
10509
10510     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10511
10512     /* now generate the jump labels */
10513     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10514          jtab = setNextItem(IC_JTLABELS(ic))) {
10515         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10516         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10517         
10518     }
10519
10520 }
10521
10522 /*-----------------------------------------------------------------*/
10523 /* genMixedOperation - gen code for operators between mixed types  */
10524 /*-----------------------------------------------------------------*/
10525 /*
10526   TSD - Written for the PIC port - but this unfortunately is buggy.
10527   This routine is good in that it is able to efficiently promote 
10528   types to different (larger) sizes. Unfortunately, the temporary
10529   variables that are optimized out by this routine are sometimes
10530   used in other places. So until I know how to really parse the 
10531   iCode tree, I'm going to not be using this routine :(.
10532 */
10533 static int genMixedOperation (iCode *ic)
10534 {
10535 #if 0
10536   operand *result = IC_RESULT(ic);
10537   sym_link *ctype = operandType(IC_LEFT(ic));
10538   operand *right = IC_RIGHT(ic);
10539   int ret = 0;
10540   int big,small;
10541   int offset;
10542
10543   iCode *nextic;
10544   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10545
10546   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10547
10548   nextic = ic->next;
10549   if(!nextic)
10550     return 0;
10551
10552   nextright = IC_RIGHT(nextic);
10553   nextleft  = IC_LEFT(nextic);
10554   nextresult = IC_RESULT(nextic);
10555
10556   pic16_aopOp(right,ic,FALSE);
10557   pic16_aopOp(result,ic,FALSE);
10558   pic16_aopOp(nextright,  nextic, FALSE);
10559   pic16_aopOp(nextleft,   nextic, FALSE);
10560   pic16_aopOp(nextresult, nextic, FALSE);
10561
10562   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10563
10564     operand *t = right;
10565     right = nextright;
10566     nextright = t; 
10567
10568     pic16_emitcode(";remove right +","");
10569
10570   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10571 /*
10572     operand *t = right;
10573     right = nextleft;
10574     nextleft = t; 
10575 */
10576     pic16_emitcode(";remove left +","");
10577   } else
10578     return 0;
10579
10580   big = AOP_SIZE(nextleft);
10581   small = AOP_SIZE(nextright);
10582
10583   switch(nextic->op) {
10584
10585   case '+':
10586     pic16_emitcode(";optimize a +","");
10587     /* if unsigned or not an integral type */
10588     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10589       pic16_emitcode(";add a bit to something","");
10590     } else {
10591
10592       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10593
10594       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10595         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10596         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10597       } else
10598         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10599
10600       offset = 0;
10601       while(--big) {
10602
10603         offset++;
10604
10605         if(--small) {
10606           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10607             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10608             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10609           }
10610
10611           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10612           emitSKPNC;
10613           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10614                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10615                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10616           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10617           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10618
10619         } else {
10620           pic16_emitcode("rlf","known_zero,w");
10621
10622           /*
10623             if right is signed
10624               btfsc  right,7
10625                addlw ff
10626           */
10627           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10628             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10629             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10630           } else {
10631             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10632           }
10633         }
10634       }
10635       ret = 1;
10636     }
10637   }
10638   ret = 1;
10639
10640 release:
10641   pic16_freeAsmop(right,NULL,ic,TRUE);
10642   pic16_freeAsmop(result,NULL,ic,TRUE);
10643   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10644   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10645   if(ret)
10646     nextic->generated = 1;
10647
10648   return ret;
10649 #else
10650   return 0;
10651 #endif
10652 }
10653 /*-----------------------------------------------------------------*/
10654 /* genCast - gen code for casting                                  */
10655 /*-----------------------------------------------------------------*/
10656 static void genCast (iCode *ic)
10657 {
10658   operand *result = IC_RESULT(ic);
10659   sym_link *ctype = operandType(IC_LEFT(ic));
10660   sym_link *rtype = operandType(IC_RIGHT(ic));
10661   operand *right = IC_RIGHT(ic);
10662   int size, offset ;
10663
10664         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10665         /* if they are equivalent then do nothing */
10666         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10667                 return ;
10668
10669         pic16_aopOp(right,ic,FALSE) ;
10670         pic16_aopOp(result,ic,FALSE);
10671
10672         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10673
10674         /* if the result is a bit */
10675         if (AOP_TYPE(result) == AOP_CRY) {
10676         
10677                 /* if the right size is a literal then
10678                  * we know what the value is */
10679                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10680
10681                 if (AOP_TYPE(right) == AOP_LIT) {
10682                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10683                                 pic16_popGet(AOP(result),0));
10684
10685                         if (((int) operandLitValue(right))) 
10686                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10687                                         AOP(result)->aopu.aop_dir,
10688                                         AOP(result)->aopu.aop_dir);
10689                         else
10690                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10691                                         AOP(result)->aopu.aop_dir,
10692                                         AOP(result)->aopu.aop_dir);
10693                         goto release;
10694                 }
10695
10696                 /* the right is also a bit variable */
10697                 if (AOP_TYPE(right) == AOP_CRY) {
10698                         emitCLRC;
10699                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10700
10701                         pic16_emitcode("clrc","");
10702                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10703                                 AOP(right)->aopu.aop_dir,
10704                                 AOP(right)->aopu.aop_dir);
10705                         pic16_aopPut(AOP(result),"c",0);
10706                         goto release ;
10707                 }
10708
10709                 /* we need to or */
10710                 if (AOP_TYPE(right) == AOP_REG) {
10711                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10712                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10713                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10714                 }
10715                 pic16_toBoolean(right);
10716                 pic16_aopPut(AOP(result),"a",0);
10717                 goto release ;
10718         }
10719
10720         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10721           int offset = 1;
10722
10723                 size = AOP_SIZE(result);
10724
10725                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10726
10727                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10728                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10729                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10730
10731                 while (size--)
10732                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10733
10734                 goto release;
10735         }
10736
10737         /* if they are the same size : or less */
10738         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10739
10740                 /* if they are in the same place */
10741                 if (pic16_sameRegs(AOP(right),AOP(result)))
10742                         goto release;
10743
10744                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10745 #if 0
10746                 if (IS_PTR_CONST(rtype))
10747 #else
10748                 if (IS_CODEPTR(rtype))
10749 #endif
10750                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10751
10752 #if 0
10753                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10754 #else
10755                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10756 #endif
10757                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10758
10759 #if 0
10760                 if(AOP_TYPE(right) == AOP_IMMD) {
10761                   pCodeOp *pcop0, *pcop1, *pcop2;
10762                   symbol *sym = OP_SYMBOL( right );
10763
10764                         size = AOP_SIZE(result);
10765                         /* low */
10766                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10767                         /* high */
10768                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10769                         /* upper */
10770                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10771         
10772                         if (size == 3) {
10773                                 pic16_emitpcode(POC_MOVLW, pcop0);
10774                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10775                                 pic16_emitpcode(POC_MOVLW, pcop1);
10776                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10777                                 pic16_emitpcode(POC_MOVLW, pcop2);
10778                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10779                         } else
10780                         if (size == 2) {
10781                                 pic16_emitpcode(POC_MOVLW, pcop0);
10782                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10783                                 pic16_emitpcode(POC_MOVLW, pcop1);
10784                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10785                         } else {
10786                                 pic16_emitpcode(POC_MOVLW, pcop0);
10787                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10788                         }
10789                 } else
10790 #endif
10791                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10792                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10793                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10794                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10795                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10796                         if(AOP_SIZE(result) <2)
10797                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10798                 } else {
10799                         /* if they in different places then copy */
10800                         size = AOP_SIZE(result);
10801                         offset = 0 ;
10802                         while (size--) {
10803                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10804                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10805                                 offset++;
10806                         }
10807                 }
10808                 goto release;
10809         }
10810
10811         /* if the result is of type pointer */
10812         if (IS_PTR(ctype)) {
10813           int p_type;
10814           sym_link *type = operandType(right);
10815           sym_link *etype = getSpec(type);
10816
10817                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10818
10819                 /* pointer to generic pointer */
10820                 if (IS_GENPTR(ctype)) {
10821                   char *l = zero;
10822             
10823                         if (IS_PTR(type)) 
10824                                 p_type = DCL_TYPE(type);
10825                         else {
10826                 /* we have to go by the storage class */
10827                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10828
10829 /*              if (SPEC_OCLS(etype)->codesp )  */
10830 /*                  p_type = CPOINTER ;  */
10831 /*              else */
10832 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10833 /*                      p_type = FPOINTER ; */
10834 /*                  else */
10835 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10836 /*                          p_type = PPOINTER; */
10837 /*                      else */
10838 /*                          if (SPEC_OCLS(etype) == idata ) */
10839 /*                              p_type = IPOINTER ; */
10840 /*                          else */
10841 /*                              p_type = POINTER ; */
10842             }
10843                 
10844             /* the first two bytes are known */
10845       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10846             size = GPTRSIZE - 1; 
10847             offset = 0 ;
10848             while (size--) {
10849               if(offset < AOP_SIZE(right)) {
10850       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10851                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10852                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10853                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10854                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10855                 } else { 
10856                   pic16_aopPut(AOP(result),
10857                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10858                          offset);
10859                 }
10860               } else 
10861                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10862               offset++;
10863             }
10864             /* the last byte depending on type */
10865             switch (p_type) {
10866             case IPOINTER:
10867             case POINTER:
10868                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10869                 break;
10870             case FPOINTER:
10871               pic16_emitcode(";BUG!? ","%d",__LINE__);
10872                 l = one;
10873                 break;
10874             case CPOINTER:
10875               pic16_emitcode(";BUG!? ","%d",__LINE__);
10876                 l = "#0x02";
10877                 break;                          
10878             case PPOINTER:
10879               pic16_emitcode(";BUG!? ","%d",__LINE__);
10880                 l = "#0x03";
10881                 break;
10882                 
10883             default:
10884                 /* this should never happen */
10885                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10886                        "got unknown pointer type");
10887                 exit(1);
10888             }
10889             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10890             goto release ;
10891         }
10892         
10893         /* just copy the pointers */
10894         size = AOP_SIZE(result);
10895         offset = 0 ;
10896         while (size--) {
10897             pic16_aopPut(AOP(result),
10898                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10899                    offset);
10900             offset++;
10901         }
10902         goto release ;
10903     }
10904     
10905
10906
10907     /* so we now know that the size of destination is greater
10908     than the size of the source.
10909     Now, if the next iCode is an operator then we might be
10910     able to optimize the operation without performing a cast.
10911     */
10912     if(genMixedOperation(ic))
10913       goto release;
10914
10915     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10916     
10917     /* we move to result for the size of source */
10918     size = AOP_SIZE(right);
10919     offset = 0 ;
10920     while (size--) {
10921       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10922       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10923       offset++;
10924     }
10925
10926     /* now depending on the sign of the destination */
10927     size = AOP_SIZE(result) - AOP_SIZE(right);
10928     /* if unsigned or not an integral type */
10929     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10930       while (size--)
10931         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10932     } else {
10933       /* we need to extend the sign :( */
10934
10935       if(size == 1) {
10936         /* Save one instruction of casting char to int */
10937         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10938         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10939         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10940       } else {
10941         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10942
10943         if(offset)
10944           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10945         else
10946           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10947         
10948         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10949
10950         while (size--)
10951           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10952       }
10953     }
10954
10955 release:
10956     pic16_freeAsmop(right,NULL,ic,TRUE);
10957     pic16_freeAsmop(result,NULL,ic,TRUE);
10958
10959 }
10960
10961 /*-----------------------------------------------------------------*/
10962 /* genDjnz - generate decrement & jump if not zero instrucion      */
10963 /*-----------------------------------------------------------------*/
10964 static int genDjnz (iCode *ic, iCode *ifx)
10965 {
10966     symbol *lbl, *lbl1;
10967     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10968
10969     if (!ifx)
10970         return 0;
10971     
10972     /* if the if condition has a false label
10973        then we cannot save */
10974     if (IC_FALSE(ifx))
10975         return 0;
10976
10977     /* if the minus is not of the form 
10978        a = a - 1 */
10979     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10980         !IS_OP_LITERAL(IC_RIGHT(ic)))
10981         return 0;
10982
10983     if (operandLitValue(IC_RIGHT(ic)) != 1)
10984         return 0;
10985
10986     /* if the size of this greater than one then no
10987        saving */
10988     if (getSize(operandType(IC_RESULT(ic))) > 1)
10989         return 0;
10990
10991     /* otherwise we can save BIG */
10992     lbl = newiTempLabel(NULL);
10993     lbl1= newiTempLabel(NULL);
10994
10995     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10996     
10997     if (IS_AOP_PREG(IC_RESULT(ic))) {
10998         pic16_emitcode("dec","%s",
10999                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11000         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11001         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11002     } else {    
11003
11004
11005       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11006       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11007
11008       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11009       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11010
11011     }
11012 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11013 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11014 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11015 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11016
11017     
11018     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11019     ifx->generated = 1;
11020     return 1;
11021 }
11022
11023 /*-----------------------------------------------------------------*/
11024 /* genReceive - generate code for a receive iCode                  */
11025 /*-----------------------------------------------------------------*/
11026 static void genReceive (iCode *ic)
11027 {    
11028         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11029
11030         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11031                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11032                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11033
11034           int size = getSize(operandType(IC_RESULT(ic)));
11035           int offset =  pic16_fReturnSizePic - size;
11036
11037                 while (size--) {
11038                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11039                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11040                         offset++;
11041                 }
11042
11043                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11044
11045                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11046                 size = AOP_SIZE(IC_RESULT(ic));
11047                 offset = 0;
11048                 while (size--) {
11049                         pic16_emitcode ("pop","acc");
11050                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11051                 }
11052         } else {
11053                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11054
11055                 _G.accInUse++;
11056                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11057                 _G.accInUse--;
11058                 assignResultValue(IC_RESULT(ic), 0);
11059         }
11060
11061         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11062 }
11063
11064 /*-----------------------------------------------------------------*/
11065 /* genDummyRead - generate code for dummy read of volatiles        */
11066 /*-----------------------------------------------------------------*/
11067 static void
11068 genDummyRead (iCode * ic)
11069 {
11070   pic16_emitcode ("; genDummyRead","");
11071   pic16_emitcode ("; not implemented","");
11072
11073   ic = ic;
11074 }
11075
11076 /*-----------------------------------------------------------------*/
11077 /* genpic16Code - generate code for pic16 based controllers        */
11078 /*-----------------------------------------------------------------*/
11079 /*
11080  * At this point, ralloc.c has gone through the iCode and attempted
11081  * to optimize in a way suitable for a PIC. Now we've got to generate
11082  * PIC instructions that correspond to the iCode.
11083  *
11084  * Once the instructions are generated, we'll pass through both the
11085  * peep hole optimizer and the pCode optimizer.
11086  *-----------------------------------------------------------------*/
11087
11088 void genpic16Code (iCode *lic)
11089 {
11090     iCode *ic;
11091     int cln = 0;
11092
11093     lineHead = lineCurr = NULL;
11094
11095     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11096     pic16_addpBlock(pb);
11097
11098 #if 0
11099     /* if debug information required */
11100     if (options.debug && currFunc) {
11101       if (currFunc) {
11102         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11103         _G.debugLine = 1;
11104         if (IS_STATIC(currFunc->etype)) {
11105           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
11106           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
11107         } else {
11108           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
11109           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
11110         }
11111         _G.debugLine = 0;
11112       }
11113     }
11114 #endif
11115
11116     for (ic = lic ; ic ; ic = ic->next ) {
11117
11118       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11119         if ( cln != ic->lineno ) {
11120             if ( options.debug ) {
11121                 _G.debugLine = 1;
11122                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
11123                          FileBaseName(ic->filename),ic->lineno,
11124                          ic->level,ic->block);
11125                 _G.debugLine = 0;
11126             }
11127             
11128             if(!options.noCcodeInAsm) {
11129                 pic16_addpCode2pBlock(pb,
11130                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11131                                 printCLine(ic->filename, ic->lineno)));
11132             }
11133
11134             cln = ic->lineno ;
11135         }
11136         
11137         if(options.iCodeInAsm) {
11138                 char *l;
11139                 /* insert here code to print iCode as comment */
11140                 l = Safe_strdup(printILine(ic));
11141                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11142         }
11143         
11144         /* if the result is marked as
11145            spilt and rematerializable or code for
11146            this has already been generated then
11147            do nothing */
11148         if (resultRemat(ic) || ic->generated ) 
11149             continue ;
11150         
11151         /* depending on the operation */
11152         switch (ic->op) {
11153         case '!' :
11154             pic16_genNot(ic);
11155             break;
11156             
11157         case '~' :
11158             pic16_genCpl(ic);
11159             break;
11160             
11161         case UNARYMINUS:
11162             genUminus (ic);
11163             break;
11164             
11165         case IPUSH:
11166             genIpush (ic);
11167             break;
11168             
11169         case IPOP:
11170             /* IPOP happens only when trying to restore a 
11171                spilt live range, if there is an ifx statement
11172                following this pop then the if statement might
11173                be using some of the registers being popped which
11174                would destroy the contents of the register so
11175                we need to check for this condition and handle it */
11176             if (ic->next            && 
11177                 ic->next->op == IFX &&
11178                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11179                 genIfx (ic->next,ic);
11180             else
11181                 genIpop (ic);
11182             break; 
11183             
11184         case CALL:
11185             genCall (ic);
11186             break;
11187             
11188         case PCALL:
11189             genPcall (ic);
11190             break;
11191             
11192         case FUNCTION:
11193             genFunction (ic);
11194             break;
11195             
11196         case ENDFUNCTION:
11197             genEndFunction (ic);
11198             break;
11199             
11200         case RETURN:
11201             genRet (ic);
11202             break;
11203             
11204         case LABEL:
11205             genLabel (ic);
11206             break;
11207             
11208         case GOTO:
11209             genGoto (ic);
11210             break;
11211             
11212         case '+' :
11213             pic16_genPlus (ic) ;
11214             break;
11215             
11216         case '-' :
11217             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11218                 pic16_genMinus (ic);
11219             break;
11220             
11221         case '*' :
11222             genMult (ic);
11223             break;
11224             
11225         case '/' :
11226             genDiv (ic) ;
11227             break;
11228             
11229         case '%' :
11230             genMod (ic);
11231             break;
11232             
11233         case '>' :
11234             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11235             break;
11236             
11237         case '<' :
11238             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11239             break;
11240             
11241         case LE_OP:
11242         case GE_OP:
11243         case NE_OP:
11244             
11245             /* note these two are xlated by algebraic equivalence
11246                during parsing SDCC.y */
11247             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11248                    "got '>=' or '<=' shouldn't have come here");
11249             break;      
11250             
11251         case EQ_OP:
11252             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11253             break;          
11254             
11255         case AND_OP:
11256             genAndOp (ic);
11257             break;
11258             
11259         case OR_OP:
11260             genOrOp (ic);
11261             break;
11262             
11263         case '^' :
11264             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11265             break;
11266             
11267         case '|' :
11268                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11269             break;
11270             
11271         case BITWISEAND:
11272             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11273             break;
11274             
11275         case INLINEASM:
11276             genInline (ic);
11277             break;
11278             
11279         case RRC:
11280             genRRC (ic);
11281             break;
11282             
11283         case RLC:
11284             genRLC (ic);
11285             break;
11286             
11287         case GETHBIT:
11288             genGetHbit (ic);
11289             break;
11290             
11291         case LEFT_OP:
11292             genLeftShift (ic);
11293             break;
11294             
11295         case RIGHT_OP:
11296             genRightShift (ic);
11297             break;
11298             
11299         case GET_VALUE_AT_ADDRESS:
11300             genPointerGet(ic);
11301             break;
11302             
11303         case '=' :
11304             if (POINTER_SET(ic))
11305                 genPointerSet(ic);
11306             else
11307                 genAssign(ic);
11308             break;
11309             
11310         case IFX:
11311             genIfx (ic,NULL);
11312             break;
11313             
11314         case ADDRESS_OF:
11315             genAddrOf (ic);
11316             break;
11317             
11318         case JUMPTABLE:
11319             genJumpTab (ic);
11320             break;
11321             
11322         case CAST:
11323             genCast (ic);
11324             break;
11325             
11326         case RECEIVE:
11327             genReceive(ic);
11328             break;
11329             
11330         case SEND:
11331             addSet(&_G.sendSet,ic);
11332             break;
11333
11334         case DUMMY_READ_VOLATILE:
11335           genDummyRead (ic);
11336           break;
11337
11338         default :
11339             ic = ic;
11340         }
11341     }
11342
11343
11344     /* now we are ready to call the
11345        peep hole optimizer */
11346     if (!options.nopeep) {
11347       peepHole (&lineHead);
11348     }
11349     /* now do the actual printing */
11350     printLine (lineHead,codeOutFile);
11351
11352 #ifdef PCODE_DEBUG
11353     DFPRINTF((stderr,"printing pBlock\n\n"));
11354     pic16_printpBlock(stdout,pb);
11355 #endif
11356
11357     return;
11358 }
11359