a83211c09cf5117fe0480a360ada5814efcef2f3
[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     /* the code below is completely untested
5896      * it just allows ulong2fs.c compile -- VR */
5897          
5898     ic = ic->next;
5899     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5900                                         __FILE__, __FUNCTION__, __LINE__);
5901         
5902     /* if this has register type condition and
5903     the next instruction is ifx with the same operand
5904     and live to of the operand is upto the ifx only then */
5905     if (ic->next &&
5906         ic->next->op == IFX &&
5907         IC_COND(ic->next)->key == op->key &&
5908         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5909         return ic->next;
5910
5911     if (ic->next &&
5912         ic->next->op == IFX &&
5913         IC_COND(ic->next)->key == op->key) {
5914       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5915       return ic->next;
5916     }
5917
5918     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5919                                         __FILE__, __FUNCTION__, __LINE__);
5920
5921 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5922
5923     return NULL;
5924 }
5925 /*-----------------------------------------------------------------*/
5926 /* genAndOp - for && operation                                     */
5927 /*-----------------------------------------------------------------*/
5928 static void genAndOp (iCode *ic)
5929 {
5930     operand *left,*right, *result;
5931 /*     symbol *tlbl; */
5932
5933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5934     /* note here that && operations that are in an
5935     if statement are taken away by backPatchLabels
5936     only those used in arthmetic operations remain */
5937     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5938     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5939     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5940
5941     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5942
5943     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5944     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5945     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5946
5947     /* if both are bit variables */
5948 /*     if (AOP_TYPE(left) == AOP_CRY && */
5949 /*         AOP_TYPE(right) == AOP_CRY ) { */
5950 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5951 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5952 /*         pic16_outBitC(result); */
5953 /*     } else { */
5954 /*         tlbl = newiTempLabel(NULL); */
5955 /*         pic16_toBoolean(left);     */
5956 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5957 /*         pic16_toBoolean(right); */
5958 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5959 /*         pic16_outBitAcc(result); */
5960 /*     } */
5961
5962     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5963     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5964     pic16_freeAsmop(result,NULL,ic,TRUE);
5965 }
5966
5967
5968 /*-----------------------------------------------------------------*/
5969 /* genOrOp - for || operation                                      */
5970 /*-----------------------------------------------------------------*/
5971 /*
5972   tsd pic port -
5973   modified this code, but it doesn't appear to ever get called
5974 */
5975
5976 static void genOrOp (iCode *ic)
5977 {
5978     operand *left,*right, *result;
5979     symbol *tlbl;
5980
5981     /* note here that || operations that are in an
5982     if statement are taken away by backPatchLabels
5983     only those used in arthmetic operations remain */
5984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5985     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5986     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5987     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5988
5989     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5990
5991     /* if both are bit variables */
5992     if (AOP_TYPE(left) == AOP_CRY &&
5993         AOP_TYPE(right) == AOP_CRY ) {
5994       pic16_emitcode("clrc","");
5995       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5996                AOP(left)->aopu.aop_dir,
5997                AOP(left)->aopu.aop_dir);
5998       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5999                AOP(right)->aopu.aop_dir,
6000                AOP(right)->aopu.aop_dir);
6001       pic16_emitcode("setc","");
6002
6003     } else {
6004         tlbl = newiTempLabel(NULL);
6005         pic16_toBoolean(left);
6006         emitSKPZ;
6007         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6008         pic16_toBoolean(right);
6009         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6010
6011         pic16_outBitAcc(result);
6012     }
6013
6014     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6015     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6016     pic16_freeAsmop(result,NULL,ic,TRUE);            
6017 }
6018
6019 /*-----------------------------------------------------------------*/
6020 /* isLiteralBit - test if lit == 2^n                               */
6021 /*-----------------------------------------------------------------*/
6022 static int isLiteralBit(unsigned long lit)
6023 {
6024     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6025     0x100L,0x200L,0x400L,0x800L,
6026     0x1000L,0x2000L,0x4000L,0x8000L,
6027     0x10000L,0x20000L,0x40000L,0x80000L,
6028     0x100000L,0x200000L,0x400000L,0x800000L,
6029     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6030     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6031     int idx;
6032     
6033     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6034     for(idx = 0; idx < 32; idx++)
6035         if(lit == pw[idx])
6036             return idx+1;
6037     return 0;
6038 }
6039
6040 /*-----------------------------------------------------------------*/
6041 /* continueIfTrue -                                                */
6042 /*-----------------------------------------------------------------*/
6043 static void continueIfTrue (iCode *ic)
6044 {
6045     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6046     if(IC_TRUE(ic))
6047         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6048     ic->generated = 1;
6049 }
6050
6051 /*-----------------------------------------------------------------*/
6052 /* jmpIfTrue -                                                     */
6053 /*-----------------------------------------------------------------*/
6054 static void jumpIfTrue (iCode *ic)
6055 {
6056     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6057     if(!IC_TRUE(ic))
6058         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6059     ic->generated = 1;
6060 }
6061
6062 /*-----------------------------------------------------------------*/
6063 /* jmpTrueOrFalse -                                                */
6064 /*-----------------------------------------------------------------*/
6065 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6066 {
6067     // ugly but optimized by peephole
6068     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6069     if(IC_TRUE(ic)){
6070         symbol *nlbl = newiTempLabel(NULL);
6071         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6072         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6073         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6074         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6075     }
6076     else{
6077         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6078         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6079     }
6080     ic->generated = 1;
6081 }
6082
6083 /*-----------------------------------------------------------------*/
6084 /* genAnd  - code for and                                          */
6085 /*-----------------------------------------------------------------*/
6086 static void genAnd (iCode *ic, iCode *ifx)
6087 {
6088   operand *left, *right, *result;
6089   int size, offset=0;  
6090   unsigned long lit = 0L;
6091   int bytelit = 0;
6092   resolvedIfx rIfx;
6093
6094
6095   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6096   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6097   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6098   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6099
6100   resolveIfx(&rIfx,ifx);
6101
6102   /* if left is a literal & right is not then exchange them */
6103   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6104       AOP_NEEDSACC(left)) {
6105     operand *tmp = right ;
6106     right = left;
6107     left = tmp;
6108   }
6109
6110   /* if result = right then exchange them */
6111   if(pic16_sameRegs(AOP(result),AOP(right))){
6112     operand *tmp = right ;
6113     right = left;
6114     left = tmp;
6115   }
6116
6117   /* if right is bit then exchange them */
6118   if (AOP_TYPE(right) == AOP_CRY &&
6119       AOP_TYPE(left) != AOP_CRY){
6120     operand *tmp = right ;
6121     right = left;
6122     left = tmp;
6123   }
6124   if(AOP_TYPE(right) == AOP_LIT)
6125     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6126
6127   size = AOP_SIZE(result);
6128
6129   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6130
6131   // if(bit & yy)
6132   // result = bit & yy;
6133   if (AOP_TYPE(left) == AOP_CRY){
6134     // c = bit & literal;
6135     if(AOP_TYPE(right) == AOP_LIT){
6136       if(lit & 1) {
6137         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6138           // no change
6139           goto release;
6140         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6141       } else {
6142         // bit(result) = 0;
6143         if(size && (AOP_TYPE(result) == AOP_CRY)){
6144           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6145           goto release;
6146         }
6147         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6148           jumpIfTrue(ifx);
6149           goto release;
6150         }
6151         pic16_emitcode("clr","c");
6152       }
6153     } else {
6154       if (AOP_TYPE(right) == AOP_CRY){
6155         // c = bit & bit;
6156         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6157         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6158       } else {
6159         // c = bit & val;
6160         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6161         // c = lsb
6162         pic16_emitcode("rrc","a");
6163         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6164       }
6165     }
6166     // bit = c
6167     // val = c
6168     if(size)
6169       pic16_outBitC(result);
6170     // if(bit & ...)
6171     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6172       genIfxJump(ifx, "c");           
6173     goto release ;
6174   }
6175
6176   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6177   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6178   if((AOP_TYPE(right) == AOP_LIT) &&
6179      (AOP_TYPE(result) == AOP_CRY) &&
6180      (AOP_TYPE(left) != AOP_CRY)){
6181     int posbit = isLiteralBit(lit);
6182     /* left &  2^n */
6183     if(posbit){
6184       posbit--;
6185       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6186       // bit = left & 2^n
6187       if(size)
6188         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6189       // if(left &  2^n)
6190       else{
6191         if(ifx){
6192 /*
6193           if(IC_TRUE(ifx)) {
6194             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6195             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6196           } else {
6197             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6198             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6199           }
6200 */
6201           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6202                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6203           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6204           
6205           ifx->generated = 1;
6206         }
6207         goto release;
6208       }
6209     } else {
6210       symbol *tlbl = newiTempLabel(NULL);
6211       int sizel = AOP_SIZE(left);
6212       if(size)
6213         pic16_emitcode("setb","c");
6214       while(sizel--){
6215         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6216           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6217           // byte ==  2^n ?
6218           if((posbit = isLiteralBit(bytelit)) != 0)
6219             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6220           else{
6221             if(bytelit != 0x0FFL)
6222               pic16_emitcode("anl","a,%s",
6223                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6224             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6225           }
6226         }
6227         offset++;
6228       }
6229       // bit = left & literal
6230       if(size){
6231         pic16_emitcode("clr","c");
6232         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6233       }
6234       // if(left & literal)
6235       else{
6236         if(ifx)
6237           jmpTrueOrFalse(ifx, tlbl);
6238         goto release ;
6239       }
6240     }
6241     pic16_outBitC(result);
6242     goto release ;
6243   }
6244
6245   /* if left is same as result */
6246   if(pic16_sameRegs(AOP(result),AOP(left))){
6247     int know_W = -1;
6248     for(;size--; offset++,lit>>=8) {
6249       if(AOP_TYPE(right) == AOP_LIT){
6250         switch(lit & 0xff) {
6251         case 0x00:
6252           /*  and'ing with 0 has clears the result */
6253 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6254           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6255           break;
6256         case 0xff:
6257           /* and'ing with 0xff is a nop when the result and left are the same */
6258           break;
6259
6260         default:
6261           {
6262             int p = my_powof2( (~lit) & 0xff );
6263             if(p>=0) {
6264               /* only one bit is set in the literal, so use a bcf instruction */
6265 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6266               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6267
6268             } else {
6269               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6270               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6271               if(know_W != (lit&0xff))
6272                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6273               know_W = lit &0xff;
6274               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6275             }
6276           }    
6277         }
6278       } else {
6279         if (AOP_TYPE(left) == AOP_ACC) {
6280           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6281         } else {                    
6282           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6283           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6284
6285         }
6286       }
6287     }
6288
6289   } else {
6290     // left & result in different registers
6291     if(AOP_TYPE(result) == AOP_CRY){
6292       // result = bit
6293       // if(size), result in bit
6294       // if(!size && ifx), conditional oper: if(left & right)
6295       symbol *tlbl = newiTempLabel(NULL);
6296       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6297       if(size)
6298         pic16_emitcode("setb","c");
6299       while(sizer--){
6300         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6301         pic16_emitcode("anl","a,%s",
6302                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6303         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6304         offset++;
6305       }
6306       if(size){
6307         CLRC;
6308         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6309         pic16_outBitC(result);
6310       } else if(ifx)
6311         jmpTrueOrFalse(ifx, tlbl);
6312     } else {
6313       for(;(size--);offset++) {
6314         // normal case
6315         // result = left & right
6316         if(AOP_TYPE(right) == AOP_LIT){
6317           int t = (lit >> (offset*8)) & 0x0FFL;
6318           switch(t) { 
6319           case 0x00:
6320             pic16_emitcode("clrf","%s",
6321                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6322             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6323             break;
6324           case 0xff:
6325             pic16_emitcode("movf","%s,w",
6326                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6327             pic16_emitcode("movwf","%s",
6328                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6329             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6330             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6331             break;
6332           default:
6333             pic16_emitcode("movlw","0x%x",t);
6334             pic16_emitcode("andwf","%s,w",
6335                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6336             pic16_emitcode("movwf","%s",
6337                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6338               
6339             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6340             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6341             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6342           }
6343           continue;
6344         }
6345
6346         if (AOP_TYPE(left) == AOP_ACC) {
6347           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6348           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6349         } else {
6350           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6351           pic16_emitcode("andwf","%s,w",
6352                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6353           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6354           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6355         }
6356         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6357         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6358       }
6359     }
6360   }
6361
6362   release :
6363     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6364   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6365   pic16_freeAsmop(result,NULL,ic,TRUE);     
6366 }
6367
6368 /*-----------------------------------------------------------------*/
6369 /* genOr  - code for or                                            */
6370 /*-----------------------------------------------------------------*/
6371 static void genOr (iCode *ic, iCode *ifx)
6372 {
6373     operand *left, *right, *result;
6374     int size, offset=0;
6375     unsigned long lit = 0L;
6376
6377     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6378
6379     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6380     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6381     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6382
6383     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6384
6385     /* if left is a literal & right is not then exchange them */
6386     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6387         AOP_NEEDSACC(left)) {
6388         operand *tmp = right ;
6389         right = left;
6390         left = tmp;
6391     }
6392
6393     /* if result = right then exchange them */
6394     if(pic16_sameRegs(AOP(result),AOP(right))){
6395         operand *tmp = right ;
6396         right = left;
6397         left = tmp;
6398     }
6399
6400     /* if right is bit then exchange them */
6401     if (AOP_TYPE(right) == AOP_CRY &&
6402         AOP_TYPE(left) != AOP_CRY){
6403         operand *tmp = right ;
6404         right = left;
6405         left = tmp;
6406     }
6407
6408     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6409
6410     if(AOP_TYPE(right) == AOP_LIT)
6411         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6412
6413     size = AOP_SIZE(result);
6414
6415     // if(bit | yy)
6416     // xx = bit | yy;
6417     if (AOP_TYPE(left) == AOP_CRY){
6418         if(AOP_TYPE(right) == AOP_LIT){
6419             // c = bit & literal;
6420             if(lit){
6421                 // lit != 0 => result = 1
6422                 if(AOP_TYPE(result) == AOP_CRY){
6423                   if(size)
6424                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6425                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6426                   //     AOP(result)->aopu.aop_dir,
6427                   //     AOP(result)->aopu.aop_dir);
6428                     else if(ifx)
6429                         continueIfTrue(ifx);
6430                     goto release;
6431                 }
6432             } else {
6433                 // lit == 0 => result = left
6434                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6435                     goto release;
6436                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6437             }
6438         } else {
6439             if (AOP_TYPE(right) == AOP_CRY){
6440               if(pic16_sameRegs(AOP(result),AOP(left))){
6441                 // c = bit | bit;
6442                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6443                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6444                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6445
6446                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6447                          AOP(result)->aopu.aop_dir,
6448                          AOP(result)->aopu.aop_dir);
6449                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6450                          AOP(right)->aopu.aop_dir,
6451                          AOP(right)->aopu.aop_dir);
6452                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6453                          AOP(result)->aopu.aop_dir,
6454                          AOP(result)->aopu.aop_dir);
6455               } else {
6456                 if( AOP_TYPE(result) == AOP_ACC) {
6457                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6458                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6459                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6460                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6461
6462                 } else {
6463
6464                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6465                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6466                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6467                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6468
6469                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6470                                  AOP(result)->aopu.aop_dir,
6471                                  AOP(result)->aopu.aop_dir);
6472                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6473                                  AOP(right)->aopu.aop_dir,
6474                                  AOP(right)->aopu.aop_dir);
6475                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6476                                  AOP(left)->aopu.aop_dir,
6477                                  AOP(left)->aopu.aop_dir);
6478                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6479                                  AOP(result)->aopu.aop_dir,
6480                                  AOP(result)->aopu.aop_dir);
6481                 }
6482               }
6483             } else {
6484                 // c = bit | val;
6485                 symbol *tlbl = newiTempLabel(NULL);
6486                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6487
6488
6489                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6490                 if( AOP_TYPE(right) == AOP_ACC) {
6491                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6492                   emitSKPNZ;
6493                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6494                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6495                 }
6496
6497
6498
6499                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6500                     pic16_emitcode(";XXX setb","c");
6501                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6502                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6503                 pic16_toBoolean(right);
6504                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6505                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6506                     jmpTrueOrFalse(ifx, tlbl);
6507                     goto release;
6508                 } else {
6509                     CLRC;
6510                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6511                 }
6512             }
6513         }
6514         // bit = c
6515         // val = c
6516         if(size)
6517             pic16_outBitC(result);
6518         // if(bit | ...)
6519         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6520             genIfxJump(ifx, "c");           
6521         goto release ;
6522     }
6523
6524     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6525     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6526     if((AOP_TYPE(right) == AOP_LIT) &&
6527        (AOP_TYPE(result) == AOP_CRY) &&
6528        (AOP_TYPE(left) != AOP_CRY)){
6529         if(lit){
6530           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6531             // result = 1
6532             if(size)
6533                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6534             else 
6535                 continueIfTrue(ifx);
6536             goto release;
6537         } else {
6538           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6539             // lit = 0, result = boolean(left)
6540             if(size)
6541                 pic16_emitcode(";XXX setb","c");
6542             pic16_toBoolean(right);
6543             if(size){
6544                 symbol *tlbl = newiTempLabel(NULL);
6545                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6546                 CLRC;
6547                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6548             } else {
6549                 genIfxJump (ifx,"a");
6550                 goto release;
6551             }
6552         }
6553         pic16_outBitC(result);
6554         goto release ;
6555     }
6556
6557     /* if left is same as result */
6558     if(pic16_sameRegs(AOP(result),AOP(left))){
6559       int know_W = -1;
6560       for(;size--; offset++,lit>>=8) {
6561         if(AOP_TYPE(right) == AOP_LIT){
6562           if((lit & 0xff) == 0)
6563             /*  or'ing with 0 has no effect */
6564             continue;
6565           else {
6566             int p = my_powof2(lit & 0xff);
6567             if(p>=0) {
6568               /* only one bit is set in the literal, so use a bsf instruction */
6569               pic16_emitpcode(POC_BSF,
6570                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6571             } else {
6572               if(know_W != (lit & 0xff))
6573                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6574               know_W = lit & 0xff;
6575               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6576             }
6577                     
6578           }
6579         } else {
6580           if (AOP_TYPE(left) == AOP_ACC) {
6581             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6582             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6583           } else {                  
6584             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6585             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6586
6587             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6589
6590           }
6591         }
6592       }
6593     } else {
6594         // left & result in different registers
6595         if(AOP_TYPE(result) == AOP_CRY){
6596             // result = bit
6597             // if(size), result in bit
6598             // if(!size && ifx), conditional oper: if(left | right)
6599             symbol *tlbl = newiTempLabel(NULL);
6600             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6601             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6602
6603
6604             if(size)
6605                 pic16_emitcode(";XXX setb","c");
6606             while(sizer--){
6607                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6608                 pic16_emitcode(";XXX orl","a,%s",
6609                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6610                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6611                 offset++;
6612             }
6613             if(size){
6614                 CLRC;
6615                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6616                 pic16_outBitC(result);
6617             } else if(ifx)
6618                 jmpTrueOrFalse(ifx, tlbl);
6619         } else for(;(size--);offset++){
6620           // normal case
6621           // result = left & right
6622           if(AOP_TYPE(right) == AOP_LIT){
6623             int t = (lit >> (offset*8)) & 0x0FFL;
6624             switch(t) { 
6625             case 0x00:
6626               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6627               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6628
6629               pic16_emitcode("movf","%s,w",
6630                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6631               pic16_emitcode("movwf","%s",
6632                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6633               break;
6634             default:
6635               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6636               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6637               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6638
6639               pic16_emitcode("movlw","0x%x",t);
6640               pic16_emitcode("iorwf","%s,w",
6641                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6642               pic16_emitcode("movwf","%s",
6643                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6644               
6645             }
6646             continue;
6647           }
6648
6649           // faster than result <- left, anl result,right
6650           // and better if result is SFR
6651           if (AOP_TYPE(left) == AOP_ACC) {
6652             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6653             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6654           } else {
6655             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6656             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6657
6658             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6659             pic16_emitcode("iorwf","%s,w",
6660                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6661           }
6662           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6663           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6664         }
6665     }
6666
6667 release :
6668     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6669     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6670     pic16_freeAsmop(result,NULL,ic,TRUE);     
6671 }
6672
6673 /*-----------------------------------------------------------------*/
6674 /* genXor - code for xclusive or                                   */
6675 /*-----------------------------------------------------------------*/
6676 static void genXor (iCode *ic, iCode *ifx)
6677 {
6678   operand *left, *right, *result;
6679   int size, offset=0;
6680   unsigned long lit = 0L;
6681
6682   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6683
6684   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6685   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6686   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6687
6688   /* if left is a literal & right is not ||
6689      if left needs acc & right does not */
6690   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6691       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6692     operand *tmp = right ;
6693     right = left;
6694     left = tmp;
6695   }
6696
6697   /* if result = right then exchange them */
6698   if(pic16_sameRegs(AOP(result),AOP(right))){
6699     operand *tmp = right ;
6700     right = left;
6701     left = tmp;
6702   }
6703
6704   /* if right is bit then exchange them */
6705   if (AOP_TYPE(right) == AOP_CRY &&
6706       AOP_TYPE(left) != AOP_CRY){
6707     operand *tmp = right ;
6708     right = left;
6709     left = tmp;
6710   }
6711   if(AOP_TYPE(right) == AOP_LIT)
6712     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6713
6714   size = AOP_SIZE(result);
6715
6716   // if(bit ^ yy)
6717   // xx = bit ^ yy;
6718   if (AOP_TYPE(left) == AOP_CRY){
6719     if(AOP_TYPE(right) == AOP_LIT){
6720       // c = bit & literal;
6721       if(lit>>1){
6722         // lit>>1  != 0 => result = 1
6723         if(AOP_TYPE(result) == AOP_CRY){
6724           if(size)
6725             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6726             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6727           else if(ifx)
6728             continueIfTrue(ifx);
6729           goto release;
6730         }
6731         pic16_emitcode("setb","c");
6732       } else{
6733         // lit == (0 or 1)
6734         if(lit == 0){
6735           // lit == 0, result = left
6736           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6737             goto release;
6738           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6739         } else{
6740           // lit == 1, result = not(left)
6741           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6742             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6743             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6744             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6745             goto release;
6746           } else {
6747             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6748             pic16_emitcode("cpl","c");
6749           }
6750         }
6751       }
6752
6753     } else {
6754       // right != literal
6755       symbol *tlbl = newiTempLabel(NULL);
6756       if (AOP_TYPE(right) == AOP_CRY){
6757         // c = bit ^ bit;
6758         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6759       }
6760       else{
6761         int sizer = AOP_SIZE(right);
6762         // c = bit ^ val
6763         // if val>>1 != 0, result = 1
6764         pic16_emitcode("setb","c");
6765         while(sizer){
6766           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6767           if(sizer == 1)
6768             // test the msb of the lsb
6769             pic16_emitcode("anl","a,#0xfe");
6770           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6771           sizer--;
6772         }
6773         // val = (0,1)
6774         pic16_emitcode("rrc","a");
6775       }
6776       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6777       pic16_emitcode("cpl","c");
6778       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6779     }
6780     // bit = c
6781     // val = c
6782     if(size)
6783       pic16_outBitC(result);
6784     // if(bit | ...)
6785     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6786       genIfxJump(ifx, "c");           
6787     goto release ;
6788   }
6789
6790   if(pic16_sameRegs(AOP(result),AOP(left))){
6791     /* if left is same as result */
6792     for(;size--; offset++) {
6793       if(AOP_TYPE(right) == AOP_LIT){
6794         int t  = (lit >> (offset*8)) & 0x0FFL;
6795         if(t == 0x00L)
6796           continue;
6797         else
6798           if (IS_AOP_PREG(left)) {
6799             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6800             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6801             pic16_aopPut(AOP(result),"a",offset);
6802           } else {
6803             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6804             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6805             pic16_emitcode("xrl","%s,%s",
6806                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6807                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6808           }
6809       } else {
6810         if (AOP_TYPE(left) == AOP_ACC)
6811           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6812         else {
6813           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6814           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6815 /*
6816           if (IS_AOP_PREG(left)) {
6817             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6818             pic16_aopPut(AOP(result),"a",offset);
6819           } else
6820             pic16_emitcode("xrl","%s,a",
6821                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6822 */
6823         }
6824       }
6825     }
6826   } else {
6827     // left & result in different registers
6828     if(AOP_TYPE(result) == AOP_CRY){
6829       // result = bit
6830       // if(size), result in bit
6831       // if(!size && ifx), conditional oper: if(left ^ right)
6832       symbol *tlbl = newiTempLabel(NULL);
6833       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6834       if(size)
6835         pic16_emitcode("setb","c");
6836       while(sizer--){
6837         if((AOP_TYPE(right) == AOP_LIT) &&
6838            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6839           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6840         } else {
6841           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6842           pic16_emitcode("xrl","a,%s",
6843                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6844         }
6845         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6846         offset++;
6847       }
6848       if(size){
6849         CLRC;
6850         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6851         pic16_outBitC(result);
6852       } else if(ifx)
6853         jmpTrueOrFalse(ifx, tlbl);
6854     } else for(;(size--);offset++){
6855       // normal case
6856       // result = left & right
6857       if(AOP_TYPE(right) == AOP_LIT){
6858         int t = (lit >> (offset*8)) & 0x0FFL;
6859         switch(t) { 
6860         case 0x00:
6861           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6862           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6863           pic16_emitcode("movf","%s,w",
6864                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6865           pic16_emitcode("movwf","%s",
6866                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6867           break;
6868         case 0xff:
6869           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6870           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6871           pic16_emitcode("comf","%s,w",
6872                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6873           pic16_emitcode("movwf","%s",
6874                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6875           break;
6876         default:
6877           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6878           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6879           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6880           pic16_emitcode("movlw","0x%x",t);
6881           pic16_emitcode("xorwf","%s,w",
6882                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6883           pic16_emitcode("movwf","%s",
6884                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6885
6886         }
6887         continue;
6888       }
6889
6890       // faster than result <- left, anl result,right
6891       // and better if result is SFR
6892       if (AOP_TYPE(left) == AOP_ACC) {
6893         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6894         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6895       } else {
6896         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6897         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6898         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6899         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6900       }
6901       if ( AOP_TYPE(result) != AOP_ACC){
6902         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6903         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6904       }
6905     }
6906   }
6907
6908   release :
6909     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6910   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6911   pic16_freeAsmop(result,NULL,ic,TRUE);     
6912 }
6913
6914 /*-----------------------------------------------------------------*/
6915 /* genInline - write the inline code out                           */
6916 /*-----------------------------------------------------------------*/
6917 static void genInline (iCode *ic)
6918 {
6919   char *buffer, *bp, *bp1;
6920     
6921         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6922
6923         _G.inLine += (!options.asmpeep);
6924
6925         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6926         strcpy(buffer,IC_INLINE(ic));
6927
6928 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
6929
6930         /* emit each line as a code */
6931         while (*bp) {
6932                 if (*bp == '\n') {
6933                         *bp++ = '\0';
6934
6935                         if(*bp1)
6936                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6937                         bp1 = bp;
6938                 } else {
6939                         if (*bp == ':') {
6940                                 bp++;
6941                                 *bp = '\0';
6942                                 bp++;
6943
6944                                 /* print label, use this special format with NULL directive
6945                                  * to denote that the argument should not be indented with tab */
6946                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6947                                 bp1 = bp;
6948                         } else
6949                                 bp++;
6950                 }
6951         }
6952
6953         if ((bp1 != bp) && *bp1)
6954                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6955
6956
6957     Safe_free(buffer);
6958
6959     _G.inLine -= (!options.asmpeep);
6960 }
6961
6962 /*-----------------------------------------------------------------*/
6963 /* genRRC - rotate right with carry                                */
6964 /*-----------------------------------------------------------------*/
6965 static void genRRC (iCode *ic)
6966 {
6967   operand *left , *result ;
6968   int size, offset = 0, same;
6969
6970   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6971
6972   /* rotate right with carry */
6973   left = IC_LEFT(ic);
6974   result=IC_RESULT(ic);
6975   pic16_aopOp (left,ic,FALSE);
6976   pic16_aopOp (result,ic,FALSE);
6977
6978   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6979
6980   same = pic16_sameRegs(AOP(result),AOP(left));
6981
6982   size = AOP_SIZE(result);    
6983
6984   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6985
6986   /* get the lsb and put it into the carry */
6987   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6988
6989   offset = 0 ;
6990
6991   while(size--) {
6992
6993     if(same) {
6994       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6995     } else {
6996       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6997       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6998     }
6999
7000     offset++;
7001   }
7002
7003   pic16_freeAsmop(left,NULL,ic,TRUE);
7004   pic16_freeAsmop(result,NULL,ic,TRUE);
7005 }
7006
7007 /*-----------------------------------------------------------------*/
7008 /* genRLC - generate code for rotate left with carry               */
7009 /*-----------------------------------------------------------------*/
7010 static void genRLC (iCode *ic)
7011 {    
7012   operand *left , *result ;
7013   int size, offset = 0;
7014   int same;
7015
7016   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7017   /* rotate right with carry */
7018   left = IC_LEFT(ic);
7019   result=IC_RESULT(ic);
7020   pic16_aopOp (left,ic,FALSE);
7021   pic16_aopOp (result,ic,FALSE);
7022
7023   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7024
7025   same = pic16_sameRegs(AOP(result),AOP(left));
7026
7027   /* move it to the result */
7028   size = AOP_SIZE(result);    
7029
7030   /* get the msb and put it into the carry */
7031   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7032
7033   offset = 0 ;
7034
7035   while(size--) {
7036
7037     if(same) {
7038       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7039     } else {
7040       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7041       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7042     }
7043
7044     offset++;
7045   }
7046
7047
7048   pic16_freeAsmop(left,NULL,ic,TRUE);
7049   pic16_freeAsmop(result,NULL,ic,TRUE);
7050 }
7051
7052
7053 /* gpasm can get the highest order bit with HIGH/UPPER
7054  * so the following probably is not needed -- VR */
7055  
7056 /*-----------------------------------------------------------------*/
7057 /* genGetHbit - generates code get highest order bit               */
7058 /*-----------------------------------------------------------------*/
7059 static void genGetHbit (iCode *ic)
7060 {
7061     operand *left, *result;
7062     left = IC_LEFT(ic);
7063     result=IC_RESULT(ic);
7064     pic16_aopOp (left,ic,FALSE);
7065     pic16_aopOp (result,ic,FALSE);
7066
7067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7068     /* get the highest order byte into a */
7069     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7070     if(AOP_TYPE(result) == AOP_CRY){
7071         pic16_emitcode("rlc","a");
7072         pic16_outBitC(result);
7073     }
7074     else{
7075         pic16_emitcode("rl","a");
7076         pic16_emitcode("anl","a,#0x01");
7077         pic16_outAcc(result);
7078     }
7079
7080
7081     pic16_freeAsmop(left,NULL,ic,TRUE);
7082     pic16_freeAsmop(result,NULL,ic,TRUE);
7083 }
7084
7085 #if 0
7086 /*-----------------------------------------------------------------*/
7087 /* AccRol - rotate left accumulator by known count                 */
7088 /*-----------------------------------------------------------------*/
7089 static void AccRol (int shCount)
7090 {
7091     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7092     shCount &= 0x0007;              // shCount : 0..7
7093     switch(shCount){
7094         case 0 :
7095             break;
7096         case 1 :
7097             pic16_emitcode("rl","a");
7098             break;
7099         case 2 :
7100             pic16_emitcode("rl","a");
7101             pic16_emitcode("rl","a");
7102             break;
7103         case 3 :
7104             pic16_emitcode("swap","a");
7105             pic16_emitcode("rr","a");
7106             break;
7107         case 4 :
7108             pic16_emitcode("swap","a");
7109             break;
7110         case 5 :
7111             pic16_emitcode("swap","a");
7112             pic16_emitcode("rl","a");
7113             break;
7114         case 6 :
7115             pic16_emitcode("rr","a");
7116             pic16_emitcode("rr","a");
7117             break;
7118         case 7 :
7119             pic16_emitcode("rr","a");
7120             break;
7121     }
7122 }
7123 #endif
7124
7125 /*-----------------------------------------------------------------*/
7126 /* AccLsh - left shift accumulator by known count                  */
7127 /*-----------------------------------------------------------------*/
7128 static void AccLsh (int shCount)
7129 {
7130         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7131         switch(shCount){
7132                 case 0 :
7133                         return;
7134                         break;
7135                 case 1 :
7136                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7137                         break;
7138                 case 2 :
7139                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7140                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7141                         break;
7142                 case 3 :
7143                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7144                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7145                         break;
7146                 case 4 :
7147                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7148                         break;
7149                 case 5 :
7150                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7151                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7152                         break;
7153                 case 6 :
7154                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7155                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7156                         break;
7157                 case 7 :
7158                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7159                         break;
7160         }
7161
7162         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7163 }
7164
7165 /*-----------------------------------------------------------------*/
7166 /* AccRsh - right shift accumulator by known count                 */
7167 /*-----------------------------------------------------------------*/
7168 static void AccRsh (int shCount, int andmask)
7169 {
7170         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7171         switch(shCount){
7172                 case 0 :
7173                         return; break;
7174                 case 1 :
7175                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7176 //                      andmask = 0;    /* no need */
7177                         break;
7178                 case 2 :
7179                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7180                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7181 //                      andmask = 0;    /* no need */
7182                         break;
7183                 case 3 :
7184                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7185                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7186                         break;
7187                 case 4 :
7188                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7189                         break;
7190                 case 5 :
7191                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7192                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7193                         break;
7194                 case 6 :
7195                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7196                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7197                         break;
7198                 case 7 :
7199                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7200                         break;
7201         }
7202         
7203         if(andmask)
7204                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7205         else
7206                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7207 }
7208
7209 #if 0
7210 /*-----------------------------------------------------------------*/
7211 /* AccSRsh - signed right shift accumulator by known count                 */
7212 /*-----------------------------------------------------------------*/
7213 static void AccSRsh (int shCount)
7214 {
7215     symbol *tlbl ;
7216     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7217     if(shCount != 0){
7218         if(shCount == 1){
7219             pic16_emitcode("mov","c,acc.7");
7220             pic16_emitcode("rrc","a");
7221         } else if(shCount == 2){
7222             pic16_emitcode("mov","c,acc.7");
7223             pic16_emitcode("rrc","a");
7224             pic16_emitcode("mov","c,acc.7");
7225             pic16_emitcode("rrc","a");
7226         } else {
7227             tlbl = newiTempLabel(NULL);
7228             /* rotate right accumulator */
7229             AccRol(8 - shCount);
7230             /* and kill the higher order bits */
7231             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7232             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7233             pic16_emitcode("orl","a,#0x%02x",
7234                      (unsigned char)~SRMask[shCount]);
7235             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7236         }
7237     }
7238 }
7239 #endif
7240 /*-----------------------------------------------------------------*/
7241 /* shiftR1Left2Result - shift right one byte from left to result   */
7242 /*-----------------------------------------------------------------*/
7243 static void shiftR1Left2ResultSigned (operand *left, int offl,
7244                                 operand *result, int offr,
7245                                 int shCount)
7246 {
7247   int same;
7248
7249   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7250
7251   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7252
7253   switch(shCount) {
7254   case 1:
7255     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7256     if(same) 
7257       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7258     else {
7259       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7260       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7261     }
7262
7263     break;
7264   case 2:
7265
7266     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7267     if(same) 
7268       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7269     else {
7270       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7271       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7272     }
7273     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7274     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7275
7276     break;
7277
7278   case 3:
7279     if(same)
7280       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7281     else {
7282       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7283       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7284     }
7285
7286     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7287     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7288     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7289
7290     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7291     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7292
7293     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7294     break;
7295
7296   case 4:
7297     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7298     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7299     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7300     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7301     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7302     break;
7303   case 5:
7304     if(same) {
7305       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7306     } else {
7307       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7308       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7309     }
7310     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7311     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7312     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7313     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7314     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7315     break;
7316
7317   case 6:
7318     if(same) {
7319       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7320       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7321       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7322       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7323       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7324       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7325     } else {
7326       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7327       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7328       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7329       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7330       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7331     }
7332     break;
7333
7334   case 7:
7335     if(same) {
7336       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7337       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7338       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7339       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7340     } else {
7341       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7342       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7343       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7344     }
7345
7346   default:
7347     break;
7348   }
7349 }
7350
7351 /*-----------------------------------------------------------------*/
7352 /* shiftR1Left2Result - shift right one byte from left to result   */
7353 /*-----------------------------------------------------------------*/
7354 static void shiftR1Left2Result (operand *left, int offl,
7355                                 operand *result, int offr,
7356                                 int shCount, int sign)
7357 {
7358   int same;
7359
7360   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7361
7362   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7363
7364   /* Copy the msb into the carry if signed. */
7365   if(sign) {
7366     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7367     return;
7368   }
7369
7370
7371
7372   switch(shCount) {
7373   case 1:
7374     emitCLRC;
7375     if(same) 
7376       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7377     else {
7378       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7379       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7380     }
7381     break;
7382   case 2:
7383     emitCLRC;
7384     if(same) {
7385       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7386     } else {
7387       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7388       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7389     }
7390     emitCLRC;
7391     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7392
7393     break;
7394   case 3:
7395     if(same)
7396       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7397     else {
7398       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7399       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7400     }
7401
7402     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7403     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7404     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7405     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7406     break;
7407       
7408   case 4:
7409     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7410     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7411     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7412     break;
7413
7414   case 5:
7415     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7416     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7417     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7418     emitCLRC;
7419     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7420
7421     break;
7422   case 6:
7423
7424     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7425     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7426     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7427     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7428     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7429     break;
7430
7431   case 7:
7432
7433     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7434     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7435     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7436
7437     break;
7438
7439   default:
7440     break;
7441   }
7442 }
7443
7444 /*-----------------------------------------------------------------*/
7445 /* shiftL1Left2Result - shift left one byte from left to result    */
7446 /*-----------------------------------------------------------------*/
7447 static void shiftL1Left2Result (operand *left, int offl,
7448                                 operand *result, int offr, int shCount)
7449 {
7450   int same;
7451
7452   //    char *l;
7453   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7454
7455   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7456   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7457     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7458     //    MOVA(l);
7459     /* shift left accumulator */
7460     //AccLsh(shCount); // don't comment out just yet...
7461   //    pic16_aopPut(AOP(result),"a",offr);
7462
7463   switch(shCount) {
7464   case 1:
7465     /* Shift left 1 bit position */
7466     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7467     if(same) {
7468       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7469     } else {
7470       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7471       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7472     }
7473     break;
7474   case 2:
7475     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7476     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7477     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7478     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7479     break;
7480   case 3:
7481     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7482     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7483     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7484     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7485     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7486     break;
7487   case 4:
7488     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7489     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7490     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7491     break;
7492   case 5:
7493     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7494     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7495     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7496     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7497     break;
7498   case 6:
7499     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7500     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7501     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7502     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7503     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7504     break;
7505   case 7:
7506     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7507     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7508     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7509     break;
7510
7511   default:
7512     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7513   }
7514
7515 }
7516
7517 /*-----------------------------------------------------------------*/
7518 /* movLeft2Result - move byte from left to result                  */
7519 /*-----------------------------------------------------------------*/
7520 static void movLeft2Result (operand *left, int offl,
7521                             operand *result, int offr)
7522 {
7523   char *l;
7524   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7525   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7526     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7527
7528     if (*l == '@' && (IS_AOP_PREG(result))) {
7529       pic16_emitcode("mov","a,%s",l);
7530       pic16_aopPut(AOP(result),"a",offr);
7531     } else {
7532       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7533       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7534     }
7535   }
7536 }
7537
7538 /*-----------------------------------------------------------------*/
7539 /* shiftL2Left2Result - shift left two bytes from left to result   */
7540 /*-----------------------------------------------------------------*/
7541 static void shiftL2Left2Result (operand *left, int offl,
7542                                 operand *result, int offr, int shCount)
7543 {
7544   int same = pic16_sameRegs(AOP(result), AOP(left));
7545   int i;
7546
7547   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7548
7549   if (same && (offl != offr)) { // shift bytes
7550     if (offr > offl) {
7551        for(i=1;i>-1;i--) {
7552          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7553          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7554        }
7555     } else { // just treat as different later on
7556                 same = 0;
7557     }
7558   }
7559
7560   if(same) {
7561     switch(shCount) {
7562     case 0:
7563       break;
7564     case 1:
7565     case 2:
7566     case 3:
7567
7568       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7569       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7570       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7571
7572       while(--shCount) {
7573                 emitCLRC;
7574                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7575                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7576       }
7577
7578       break;
7579     case 4:
7580     case 5:
7581       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7582       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7583       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7584       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7585       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7586       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7587       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7588       if(shCount >=5) {
7589                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7590                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7591       }
7592       break;
7593     case 6:
7594       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7595       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7596       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7597       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7598       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7599       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7600       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7601       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7602       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7603       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7604       break;
7605     case 7:
7606       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7607       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7608       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7609       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7610       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7611     }
7612
7613   } else {
7614     switch(shCount) {
7615     case 0:
7616       break;
7617     case 1:
7618     case 2:
7619     case 3:
7620       /* note, use a mov/add for the shift since the mov has a
7621          chance of getting optimized out */
7622       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7623       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7624       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7625       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7626       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7627
7628       while(--shCount) {
7629                 emitCLRC;
7630                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7631                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7632       }
7633       break;
7634
7635     case 4:
7636     case 5:
7637       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7638       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7639       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7640       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7641       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7642       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7643       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7644       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7645
7646
7647       if(shCount == 5) {
7648                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7649                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7650       }
7651       break;
7652     case 6:
7653       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7654       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7655       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7656       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7657
7658       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7659       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7660       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7661       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7662       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7663       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7664       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7665       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7666       break;
7667     case 7:
7668       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7669       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7670       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7671       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7672       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7673     }
7674   }
7675
7676 }
7677 /*-----------------------------------------------------------------*/
7678 /* shiftR2Left2Result - shift right two bytes from left to result  */
7679 /*-----------------------------------------------------------------*/
7680 static void shiftR2Left2Result (operand *left, int offl,
7681                                 operand *result, int offr,
7682                                 int shCount, int sign)
7683 {
7684   int same = pic16_sameRegs(AOP(result), AOP(left));
7685   int i;
7686   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7687
7688   if (same && (offl != offr)) { // shift right bytes
7689     if (offr < offl) {
7690        for(i=0;i<2;i++) {
7691          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7692          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7693        }
7694     } else { // just treat as different later on
7695                 same = 0;
7696     }
7697   }
7698
7699   switch(shCount) {
7700   case 0:
7701     break;
7702   case 1:
7703   case 2:
7704   case 3:
7705     if(sign)
7706       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7707     else
7708       emitCLRC;
7709
7710     if(same) {
7711       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7712       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7713     } else {
7714       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7715       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7716       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7717       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7718     }
7719
7720     while(--shCount) {
7721       if(sign)
7722                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7723       else
7724                 emitCLRC;
7725       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7726       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7727     }
7728     break;
7729   case 4:
7730   case 5:
7731     if(same) {
7732
7733       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7734       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7735       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7736
7737       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7738       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7739       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7740       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7741     } else {
7742       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7743       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7744       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7745
7746       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7747       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7748       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7749       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7750       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7751     }
7752
7753     if(shCount >=5) {
7754       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7755       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7756     }
7757
7758     if(sign) {
7759       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7760       pic16_emitpcode(POC_BTFSC, 
7761                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7762       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7763     }
7764
7765     break;
7766
7767   case 6:
7768     if(same) {
7769
7770       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7771       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7772
7773       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7774       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7775       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7776       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7777       if(sign) {
7778         pic16_emitpcode(POC_BTFSC, 
7779                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7780         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7781       }
7782       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7783       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7784       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7785       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7786     } else {
7787       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7788       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7789       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7790       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7791       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7792       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7793       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7794       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7795       if(sign) {
7796         pic16_emitpcode(POC_BTFSC, 
7797                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7798         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7799       }
7800       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7801       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7802
7803         
7804     }
7805
7806     break;
7807   case 7:
7808     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7809     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7810     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7811     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7812     if(sign) {
7813       emitSKPNC;
7814       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7815     } else 
7816       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7817   }
7818 }
7819
7820
7821 /*-----------------------------------------------------------------*/
7822 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7823 /*-----------------------------------------------------------------*/
7824 static void shiftLLeftOrResult (operand *left, int offl,
7825                                 operand *result, int offr, int shCount)
7826 {
7827     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7828
7829     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7830     /* shift left accumulator */
7831     AccLsh(shCount);
7832     /* or with result */
7833     /* back to result */
7834     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7835 }
7836
7837 /*-----------------------------------------------------------------*/
7838 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7839 /*-----------------------------------------------------------------*/
7840 static void shiftRLeftOrResult (operand *left, int offl,
7841                                 operand *result, int offr, int shCount)
7842 {
7843     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7844     
7845     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7846     /* shift right accumulator */
7847     AccRsh(shCount, 1);
7848     /* or with result */
7849     /* back to result */
7850     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7851 }
7852
7853 /*-----------------------------------------------------------------*/
7854 /* genlshOne - left shift a one byte quantity by known count       */
7855 /*-----------------------------------------------------------------*/
7856 static void genlshOne (operand *result, operand *left, int shCount)
7857 {       
7858     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7859     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7860 }
7861
7862 /*-----------------------------------------------------------------*/
7863 /* genlshTwo - left shift two bytes by known amount != 0           */
7864 /*-----------------------------------------------------------------*/
7865 static void genlshTwo (operand *result,operand *left, int shCount)
7866 {
7867     int size;
7868     
7869     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7870     size = pic16_getDataSize(result);
7871
7872     /* if shCount >= 8 */
7873     if (shCount >= 8) {
7874         shCount -= 8 ;
7875
7876         if (size > 1){
7877             if (shCount)
7878                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7879             else 
7880                 movLeft2Result(left, LSB, result, MSB16);
7881         }
7882         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7883     }
7884
7885     /*  1 <= shCount <= 7 */
7886     else {  
7887         if(size == 1)
7888             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7889         else 
7890             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7891     }
7892 }
7893
7894 /*-----------------------------------------------------------------*/
7895 /* shiftLLong - shift left one long from left to result            */
7896 /* offr = LSB or MSB16                                             */
7897 /*-----------------------------------------------------------------*/
7898 static void shiftLLong (operand *left, operand *result, int offr )
7899 {
7900     int size = AOP_SIZE(result);
7901     int same = pic16_sameRegs(AOP(left),AOP(result));
7902         int i;
7903
7904     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7905
7906         if (same && (offr == MSB16)) { //shift one byte
7907                 for(i=size-1;i>=MSB16;i--) {
7908                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7909                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7910                 }
7911         } else {
7912                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7913         }
7914         
7915     if (size >= LSB+offr ){
7916                 if (same) {
7917                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7918                 } else {
7919                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7920                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7921                 }
7922          }
7923
7924     if(size >= MSB16+offr){
7925                 if (same) {
7926                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7927                 } else {
7928                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7929                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7930                 }
7931     }
7932
7933     if(size >= MSB24+offr){
7934                 if (same) {
7935                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7936                 } else {
7937                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7938                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7939                 }
7940     }
7941
7942     if(size > MSB32+offr){
7943                 if (same) {
7944                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7945                 } else {
7946                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7947                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7948                 }
7949     }
7950     if(offr != LSB)
7951                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7952
7953 }
7954
7955 /*-----------------------------------------------------------------*/
7956 /* genlshFour - shift four byte by a known amount != 0             */
7957 /*-----------------------------------------------------------------*/
7958 static void genlshFour (operand *result, operand *left, int shCount)
7959 {
7960     int size;
7961
7962     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7963     size = AOP_SIZE(result);
7964
7965     /* if shifting more that 3 bytes */
7966     if (shCount >= 24 ) {
7967         shCount -= 24;
7968         if (shCount)
7969             /* lowest order of left goes to the highest
7970             order of the destination */
7971             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7972         else
7973             movLeft2Result(left, LSB, result, MSB32);
7974
7975                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7976                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7977                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7978
7979         return;
7980     }
7981
7982     /* more than two bytes */
7983     else if ( shCount >= 16 ) {
7984         /* lower order two bytes goes to higher order two bytes */
7985         shCount -= 16;
7986         /* if some more remaining */
7987         if (shCount)
7988             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7989         else {
7990             movLeft2Result(left, MSB16, result, MSB32);
7991             movLeft2Result(left, LSB, result, MSB24);
7992         }
7993                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7994                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7995         return;
7996     }    
7997
7998     /* if more than 1 byte */
7999     else if ( shCount >= 8 ) {
8000         /* lower order three bytes goes to higher order  three bytes */
8001         shCount -= 8;
8002         if(size == 2){
8003             if(shCount)
8004                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8005             else
8006                 movLeft2Result(left, LSB, result, MSB16);
8007         }
8008         else{   /* size = 4 */
8009             if(shCount == 0){
8010                 movLeft2Result(left, MSB24, result, MSB32);
8011                 movLeft2Result(left, MSB16, result, MSB24);
8012                 movLeft2Result(left, LSB, result, MSB16);
8013                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8014             }
8015             else if(shCount == 1)
8016                 shiftLLong(left, result, MSB16);
8017             else{
8018                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8019                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8020                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8021                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8022             }
8023         }
8024     }
8025
8026     /* 1 <= shCount <= 7 */
8027     else if(shCount <= 3)
8028     { 
8029         shiftLLong(left, result, LSB);
8030         while(--shCount >= 1)
8031             shiftLLong(result, result, LSB);
8032     }
8033     /* 3 <= shCount <= 7, optimize */
8034     else{
8035         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8036         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8037         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8038     }
8039 }
8040
8041 /*-----------------------------------------------------------------*/
8042 /* genLeftShiftLiteral - left shifting by known count              */
8043 /*-----------------------------------------------------------------*/
8044 static void genLeftShiftLiteral (operand *left,
8045                                  operand *right,
8046                                  operand *result,
8047                                  iCode *ic)
8048 {    
8049     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8050     int size;
8051
8052     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8053     pic16_freeAsmop(right,NULL,ic,TRUE);
8054
8055     pic16_aopOp(left,ic,FALSE);
8056     pic16_aopOp(result,ic,FALSE);
8057
8058     size = getSize(operandType(result));
8059
8060 #if VIEW_SIZE
8061     pic16_emitcode("; shift left ","result %d, left %d",size,
8062              AOP_SIZE(left));
8063 #endif
8064
8065     /* I suppose that the left size >= result size */
8066     if(shCount == 0){
8067         while(size--){
8068             movLeft2Result(left, size, result, size);
8069         }
8070     }
8071
8072     else if(shCount >= (size * 8))
8073         while(size--)
8074             pic16_aopPut(AOP(result),zero,size);
8075     else{
8076         switch (size) {
8077             case 1:
8078                 genlshOne (result,left,shCount);
8079                 break;
8080
8081             case 2:
8082             case 3:
8083                 genlshTwo (result,left,shCount);
8084                 break;
8085
8086             case 4:
8087                 genlshFour (result,left,shCount);
8088                 break;
8089         }
8090     }
8091     pic16_freeAsmop(left,NULL,ic,TRUE);
8092     pic16_freeAsmop(result,NULL,ic,TRUE);
8093 }
8094
8095 /*-----------------------------------------------------------------*
8096  * genMultiAsm - repeat assembly instruction for size of register.
8097  * if endian == 1, then the high byte (i.e base address + size of 
8098  * register) is used first else the low byte is used first;
8099  *-----------------------------------------------------------------*/
8100 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8101 {
8102
8103   int offset = 0;
8104
8105   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8106
8107   if(!reg)
8108     return;
8109
8110   if(!endian) {
8111     endian = 1;
8112   } else {
8113     endian = -1;
8114     offset = size-1;
8115   }
8116
8117   while(size--) {
8118     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8119     offset += endian;
8120   }
8121
8122 }
8123 /*-----------------------------------------------------------------*/
8124 /* genLeftShift - generates code for left shifting                 */
8125 /*-----------------------------------------------------------------*/
8126 static void genLeftShift (iCode *ic)
8127 {
8128   operand *left,*right, *result;
8129   int size, offset;
8130   char *l;
8131   symbol *tlbl , *tlbl1;
8132   pCodeOp *pctemp;
8133
8134   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8135
8136   right = IC_RIGHT(ic);
8137   left  = IC_LEFT(ic);
8138   result = IC_RESULT(ic);
8139
8140   pic16_aopOp(right,ic,FALSE);
8141
8142   /* if the shift count is known then do it 
8143      as efficiently as possible */
8144   if (AOP_TYPE(right) == AOP_LIT) {
8145     genLeftShiftLiteral (left,right,result,ic);
8146     return ;
8147   }
8148
8149   /* shift count is unknown then we have to form 
8150      a loop get the loop count in B : Note: we take
8151      only the lower order byte since shifting
8152      more that 32 bits make no sense anyway, ( the
8153      largest size of an object can be only 32 bits ) */  
8154
8155     
8156   pic16_aopOp(left,ic,FALSE);
8157   pic16_aopOp(result,ic,FALSE);
8158
8159   /* now move the left to the result if they are not the
8160      same */
8161   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8162       AOP_SIZE(result) > 1) {
8163
8164     size = AOP_SIZE(result);
8165     offset=0;
8166     while (size--) {
8167       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8168       if (*l == '@' && (IS_AOP_PREG(result))) {
8169
8170         pic16_emitcode("mov","a,%s",l);
8171         pic16_aopPut(AOP(result),"a",offset);
8172       } else {
8173         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8174         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8175         //pic16_aopPut(AOP(result),l,offset);
8176       }
8177       offset++;
8178     }
8179   }
8180
8181   size = AOP_SIZE(result);
8182
8183   /* if it is only one byte then */
8184   if (size == 1) {
8185     if(optimized_for_speed) {
8186       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8187       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8188       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8189       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8190       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8191       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8192       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8193       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8194       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8195       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8196       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8197       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8198     } else {
8199
8200       tlbl = newiTempLabel(NULL);
8201       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8202                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8203                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8204       }
8205
8206       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8207       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8208       pic16_emitpLabel(tlbl->key);
8209       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8210       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8211       emitSKPC;
8212       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8213     }
8214     goto release ;
8215   }
8216     
8217   if (pic16_sameRegs(AOP(left),AOP(result))) {
8218
8219     tlbl = newiTempLabel(NULL);
8220     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8221     genMultiAsm(POC_RRCF, result, size,1);
8222     pic16_emitpLabel(tlbl->key);
8223     genMultiAsm(POC_RLCF, result, size,0);
8224     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8225     emitSKPC;
8226     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8227     goto release;
8228   }
8229
8230   //tlbl = newiTempLabel(NULL);
8231   //offset = 0 ;   
8232   //tlbl1 = newiTempLabel(NULL);
8233
8234   //reAdjustPreg(AOP(result));    
8235     
8236   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8237   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8238   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8239   //MOVA(l);
8240   //pic16_emitcode("add","a,acc");         
8241   //pic16_aopPut(AOP(result),"a",offset++);
8242   //while (--size) {
8243   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8244   //  MOVA(l);
8245   //  pic16_emitcode("rlc","a");         
8246   //  pic16_aopPut(AOP(result),"a",offset++);
8247   //}
8248   //reAdjustPreg(AOP(result));
8249
8250   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8251   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8252
8253
8254   tlbl = newiTempLabel(NULL);
8255   tlbl1= newiTempLabel(NULL);
8256
8257   size = AOP_SIZE(result);
8258   offset = 1;
8259
8260   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8261
8262   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8263
8264   /* offset should be 0, 1 or 3 */
8265   
8266   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8267   emitSKPNZ;
8268   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8269
8270   pic16_emitpcode(POC_MOVWF, pctemp);
8271
8272
8273   pic16_emitpLabel(tlbl->key);
8274
8275   emitCLRC;
8276   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8277   while(--size)
8278     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8279
8280   pic16_emitpcode(POC_DECFSZ,  pctemp);
8281   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8282   pic16_emitpLabel(tlbl1->key);
8283
8284   pic16_popReleaseTempReg(pctemp);
8285
8286
8287  release:
8288   pic16_freeAsmop (right,NULL,ic,TRUE);
8289   pic16_freeAsmop(left,NULL,ic,TRUE);
8290   pic16_freeAsmop(result,NULL,ic,TRUE);
8291 }
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genrshOne - right shift a one byte quantity by known count      */
8295 /*-----------------------------------------------------------------*/
8296 static void genrshOne (operand *result, operand *left,
8297                        int shCount, int sign)
8298 {
8299     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8300     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8301 }
8302
8303 /*-----------------------------------------------------------------*/
8304 /* genrshTwo - right shift two bytes by known amount != 0          */
8305 /*-----------------------------------------------------------------*/
8306 static void genrshTwo (operand *result,operand *left,
8307                        int shCount, int sign)
8308 {
8309   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8310   /* if shCount >= 8 */
8311   if (shCount >= 8) {
8312     shCount -= 8 ;
8313     if (shCount)
8314       shiftR1Left2Result(left, MSB16, result, LSB,
8315                          shCount, sign);
8316     else
8317       movLeft2Result(left, MSB16, result, LSB);
8318
8319     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8320
8321     if(sign) {
8322       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8323       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8324     }
8325   }
8326
8327   /*  1 <= shCount <= 7 */
8328   else
8329     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8330 }
8331
8332 /*-----------------------------------------------------------------*/
8333 /* shiftRLong - shift right one long from left to result           */
8334 /* offl = LSB or MSB16                                             */
8335 /*-----------------------------------------------------------------*/
8336 static void shiftRLong (operand *left, int offl,
8337                         operand *result, int sign)
8338 {
8339     int size = AOP_SIZE(result);
8340     int same = pic16_sameRegs(AOP(left),AOP(result));
8341     int i;
8342     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8343
8344         if (same && (offl == MSB16)) { //shift one byte right
8345                 for(i=MSB16;i<size;i++) {
8346                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8347                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8348                 }
8349         }
8350
8351     if(sign)
8352                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8353         else
8354                 emitCLRC;
8355
8356         if (same) {
8357                 if (offl == LSB)
8358                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8359         } else {
8360         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8361         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8362         }
8363
8364     if(offl == MSB16) {
8365         /* add sign of "a" */
8366         pic16_addSign(result, MSB32, sign);
8367         }
8368
8369         if (same) {
8370         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8371         } else {
8372         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8373         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8374         }
8375         
8376         if (same) {
8377         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8378         } else {
8379         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8380         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8381         }
8382
8383         if (same) {
8384         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8385         } else {
8386         if(offl == LSB){
8387                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8388                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8389         }
8390         }
8391 }
8392
8393 /*-----------------------------------------------------------------*/
8394 /* genrshFour - shift four byte by a known amount != 0             */
8395 /*-----------------------------------------------------------------*/
8396 static void genrshFour (operand *result, operand *left,
8397                         int shCount, int sign)
8398 {
8399   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8400   /* if shifting more that 3 bytes */
8401   if(shCount >= 24 ) {
8402     shCount -= 24;
8403     if(shCount)
8404       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8405     else
8406       movLeft2Result(left, MSB32, result, LSB);
8407
8408     pic16_addSign(result, MSB16, sign);
8409   }
8410   else if(shCount >= 16){
8411     shCount -= 16;
8412     if(shCount)
8413       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8414     else{
8415       movLeft2Result(left, MSB24, result, LSB);
8416       movLeft2Result(left, MSB32, result, MSB16);
8417     }
8418     pic16_addSign(result, MSB24, sign);
8419   }
8420   else if(shCount >= 8){
8421     shCount -= 8;
8422     if(shCount == 1)
8423       shiftRLong(left, MSB16, result, sign);
8424     else if(shCount == 0){
8425       movLeft2Result(left, MSB16, result, LSB);
8426       movLeft2Result(left, MSB24, result, MSB16);
8427       movLeft2Result(left, MSB32, result, MSB24);
8428       pic16_addSign(result, MSB32, sign);
8429     }
8430     else{ //shcount >= 2
8431       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8432       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8433       /* the last shift is signed */
8434       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8435       pic16_addSign(result, MSB32, sign);
8436     }
8437   }
8438   else{   /* 1 <= shCount <= 7 */
8439     if(shCount <= 2){
8440       shiftRLong(left, LSB, result, sign);
8441       if(shCount == 2)
8442         shiftRLong(result, LSB, result, sign);
8443     }
8444     else{
8445       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8446       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8447       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8448     }
8449   }
8450 }
8451
8452 /*-----------------------------------------------------------------*/
8453 /* genRightShiftLiteral - right shifting by known count            */
8454 /*-----------------------------------------------------------------*/
8455 static void genRightShiftLiteral (operand *left,
8456                                   operand *right,
8457                                   operand *result,
8458                                   iCode *ic,
8459                                   int sign)
8460 {    
8461   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8462   int lsize,res_size;
8463
8464   pic16_freeAsmop(right,NULL,ic,TRUE);
8465
8466   pic16_aopOp(left,ic,FALSE);
8467   pic16_aopOp(result,ic,FALSE);
8468
8469   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8470
8471 #if VIEW_SIZE
8472   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8473                  AOP_SIZE(left));
8474 #endif
8475
8476   lsize = pic16_getDataSize(left);
8477   res_size = pic16_getDataSize(result);
8478   /* test the LEFT size !!! */
8479
8480   /* I suppose that the left size >= result size */
8481   if(shCount == 0){
8482     while(res_size--)
8483       movLeft2Result(left, lsize, result, res_size);
8484   }
8485
8486   else if(shCount >= (lsize * 8)){
8487
8488     if(res_size == 1) {
8489       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8490       if(sign) {
8491         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8492         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8493       }
8494     } else {
8495
8496       if(sign) {
8497         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8498         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8499         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8500         while(res_size--)
8501           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8502
8503       } else {
8504
8505         while(res_size--)
8506           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8507       }
8508     }
8509   } else {
8510
8511     switch (res_size) {
8512     case 1:
8513       genrshOne (result,left,shCount,sign);
8514       break;
8515
8516     case 2:
8517       genrshTwo (result,left,shCount,sign);
8518       break;
8519
8520     case 4:
8521       genrshFour (result,left,shCount,sign);
8522       break;
8523     default :
8524       break;
8525     }
8526
8527   }
8528
8529   pic16_freeAsmop(left,NULL,ic,TRUE);
8530   pic16_freeAsmop(result,NULL,ic,TRUE);
8531 }
8532
8533 /*-----------------------------------------------------------------*/
8534 /* genSignedRightShift - right shift of signed number              */
8535 /*-----------------------------------------------------------------*/
8536 static void genSignedRightShift (iCode *ic)
8537 {
8538   operand *right, *left, *result;
8539   int size, offset;
8540   //  char *l;
8541   symbol *tlbl, *tlbl1 ;
8542   pCodeOp *pctemp;
8543
8544   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8545
8546   /* we do it the hard way put the shift count in b
8547      and loop thru preserving the sign */
8548   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8549
8550   right = IC_RIGHT(ic);
8551   left  = IC_LEFT(ic);
8552   result = IC_RESULT(ic);
8553
8554   pic16_aopOp(right,ic,FALSE);  
8555   pic16_aopOp(left,ic,FALSE);
8556   pic16_aopOp(result,ic,FALSE);
8557
8558
8559   if ( AOP_TYPE(right) == AOP_LIT) {
8560     genRightShiftLiteral (left,right,result,ic,1);
8561     return ;
8562   }
8563   /* shift count is unknown then we have to form 
8564      a loop get the loop count in B : Note: we take
8565      only the lower order byte since shifting
8566      more that 32 bits make no sense anyway, ( the
8567      largest size of an object can be only 32 bits ) */  
8568
8569   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8570   //pic16_emitcode("inc","b");
8571   //pic16_freeAsmop (right,NULL,ic,TRUE);
8572   //pic16_aopOp(left,ic,FALSE);
8573   //pic16_aopOp(result,ic,FALSE);
8574
8575   /* now move the left to the result if they are not the
8576      same */
8577   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8578       AOP_SIZE(result) > 1) {
8579
8580     size = AOP_SIZE(result);
8581     offset=0;
8582     while (size--) { 
8583       /*
8584         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8585         if (*l == '@' && IS_AOP_PREG(result)) {
8586
8587         pic16_emitcode("mov","a,%s",l);
8588         pic16_aopPut(AOP(result),"a",offset);
8589         } else
8590         pic16_aopPut(AOP(result),l,offset);
8591       */
8592       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8593       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8594
8595       offset++;
8596     }
8597   }
8598
8599   /* mov the highest order bit to OVR */    
8600   tlbl = newiTempLabel(NULL);
8601   tlbl1= newiTempLabel(NULL);
8602
8603   size = AOP_SIZE(result);
8604   offset = size - 1;
8605
8606   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8607
8608   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8609
8610   /* offset should be 0, 1 or 3 */
8611   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8612   emitSKPNZ;
8613   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8614
8615   pic16_emitpcode(POC_MOVWF, pctemp);
8616
8617
8618   pic16_emitpLabel(tlbl->key);
8619
8620   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8621   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8622
8623   while(--size) {
8624     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8625   }
8626
8627   pic16_emitpcode(POC_DECFSZ,  pctemp);
8628   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8629   pic16_emitpLabel(tlbl1->key);
8630
8631   pic16_popReleaseTempReg(pctemp);
8632 #if 0
8633   size = AOP_SIZE(result);
8634   offset = size - 1;
8635   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8636   pic16_emitcode("rlc","a");
8637   pic16_emitcode("mov","ov,c");
8638   /* if it is only one byte then */
8639   if (size == 1) {
8640     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8641     MOVA(l);
8642     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8643     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8644     pic16_emitcode("mov","c,ov");
8645     pic16_emitcode("rrc","a");
8646     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8647     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8648     pic16_aopPut(AOP(result),"a",0);
8649     goto release ;
8650   }
8651
8652   reAdjustPreg(AOP(result));
8653   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8654   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8655   pic16_emitcode("mov","c,ov");
8656   while (size--) {
8657     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8658     MOVA(l);
8659     pic16_emitcode("rrc","a");         
8660     pic16_aopPut(AOP(result),"a",offset--);
8661   }
8662   reAdjustPreg(AOP(result));
8663   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8664   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8665
8666  release:
8667 #endif
8668
8669   pic16_freeAsmop(left,NULL,ic,TRUE);
8670   pic16_freeAsmop(result,NULL,ic,TRUE);
8671   pic16_freeAsmop(right,NULL,ic,TRUE);
8672 }
8673
8674 /*-----------------------------------------------------------------*/
8675 /* genRightShift - generate code for right shifting                */
8676 /*-----------------------------------------------------------------*/
8677 static void genRightShift (iCode *ic)
8678 {
8679     operand *right, *left, *result;
8680     sym_link *letype ;
8681     int size, offset;
8682     char *l;
8683     symbol *tlbl, *tlbl1 ;
8684
8685     /* if signed then we do it the hard way preserve the
8686     sign bit moving it inwards */
8687     letype = getSpec(operandType(IC_LEFT(ic)));
8688     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8689
8690     if (!SPEC_USIGN(letype)) {
8691         genSignedRightShift (ic);
8692         return ;
8693     }
8694
8695     /* signed & unsigned types are treated the same : i.e. the
8696     signed is NOT propagated inwards : quoting from the
8697     ANSI - standard : "for E1 >> E2, is equivalent to division
8698     by 2**E2 if unsigned or if it has a non-negative value,
8699     otherwise the result is implementation defined ", MY definition
8700     is that the sign does not get propagated */
8701
8702     right = IC_RIGHT(ic);
8703     left  = IC_LEFT(ic);
8704     result = IC_RESULT(ic);
8705
8706     pic16_aopOp(right,ic,FALSE);
8707
8708     /* if the shift count is known then do it 
8709     as efficiently as possible */
8710     if (AOP_TYPE(right) == AOP_LIT) {
8711         genRightShiftLiteral (left,right,result,ic, 0);
8712         return ;
8713     }
8714
8715     /* shift count is unknown then we have to form 
8716     a loop get the loop count in B : Note: we take
8717     only the lower order byte since shifting
8718     more that 32 bits make no sense anyway, ( the
8719     largest size of an object can be only 32 bits ) */  
8720
8721     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8722     pic16_emitcode("inc","b");
8723     pic16_aopOp(left,ic,FALSE);
8724     pic16_aopOp(result,ic,FALSE);
8725
8726     /* now move the left to the result if they are not the
8727     same */
8728     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8729         AOP_SIZE(result) > 1) {
8730
8731         size = AOP_SIZE(result);
8732         offset=0;
8733         while (size--) {
8734             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8735             if (*l == '@' && IS_AOP_PREG(result)) {
8736
8737                 pic16_emitcode("mov","a,%s",l);
8738                 pic16_aopPut(AOP(result),"a",offset);
8739             } else
8740                 pic16_aopPut(AOP(result),l,offset);
8741             offset++;
8742         }
8743     }
8744
8745     tlbl = newiTempLabel(NULL);
8746     tlbl1= newiTempLabel(NULL);
8747     size = AOP_SIZE(result);
8748     offset = size - 1;
8749
8750     /* if it is only one byte then */
8751     if (size == 1) {
8752
8753       tlbl = newiTempLabel(NULL);
8754       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8755         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8756         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8757       }
8758
8759       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8760       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8761       pic16_emitpLabel(tlbl->key);
8762       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8763       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8764       emitSKPC;
8765       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8766
8767       goto release ;
8768     }
8769
8770     reAdjustPreg(AOP(result));
8771     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8772     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8773     CLRC;
8774     while (size--) {
8775         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8776         MOVA(l);
8777         pic16_emitcode("rrc","a");         
8778         pic16_aopPut(AOP(result),"a",offset--);
8779     }
8780     reAdjustPreg(AOP(result));
8781
8782     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8783     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8784
8785 release:
8786     pic16_freeAsmop(left,NULL,ic,TRUE);
8787     pic16_freeAsmop (right,NULL,ic,TRUE);
8788     pic16_freeAsmop(result,NULL,ic,TRUE);
8789 }
8790
8791 /*-----------------------------------------------------------------*/
8792 /* genUnpackBits - generates code for unpacking bits               */
8793 /*-----------------------------------------------------------------*/
8794 static void genUnpackBits (operand *result, char *rname, int ptype)
8795 {    
8796     int shCnt ;
8797     int rlen = 0 ;
8798     sym_link *etype;
8799     int offset = 0 ;
8800
8801         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8802         etype = getSpec(operandType(result));
8803
8804         /* read the first byte  */
8805         switch (ptype) {
8806                 case POINTER:
8807                 case IPOINTER:
8808                 case PPOINTER:
8809                 case FPOINTER:
8810                 case GPOINTER:
8811                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8812                         break;
8813                 case CPOINTER:
8814                         pic16_emitcode("clr","a");
8815                         pic16_emitcode("movc","a","@a+dptr");
8816                         break;
8817         }
8818         
8819
8820         /* if we have bitdisplacement then it fits   */
8821         /* into this byte completely or if length is */
8822         /* less than a byte                          */
8823         if ((shCnt = SPEC_BSTR(etype)) || 
8824                 (SPEC_BLEN(etype) <= 8))  {
8825
8826                 /* shift right acc */
8827                 AccRsh(shCnt, 0);
8828
8829                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8830                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8831
8832 /* VR -- normally I would use the following, but since we use the hack,
8833  * to avoid the masking from AccRsh, why not mask it right now? */
8834
8835 /*
8836                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8837 */
8838
8839                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8840           return ;
8841         }
8842
8843
8844
8845         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8846         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8847         exit(-1);
8848
8849     /* bit field did not fit in a byte  */
8850     rlen = SPEC_BLEN(etype) - 8;
8851     pic16_aopPut(AOP(result),"a",offset++);
8852
8853     while (1)  {
8854
8855         switch (ptype) {
8856         case POINTER:
8857         case IPOINTER:
8858             pic16_emitcode("inc","%s",rname);
8859             pic16_emitcode("mov","a,@%s",rname);
8860             break;
8861             
8862         case PPOINTER:
8863             pic16_emitcode("inc","%s",rname);
8864             pic16_emitcode("movx","a,@%s",rname);
8865             break;
8866
8867         case FPOINTER:
8868             pic16_emitcode("inc","dptr");
8869             pic16_emitcode("movx","a,@dptr");
8870             break;
8871             
8872         case CPOINTER:
8873             pic16_emitcode("clr","a");
8874             pic16_emitcode("inc","dptr");
8875             pic16_emitcode("movc","a","@a+dptr");
8876             break;
8877             
8878         case GPOINTER:
8879             pic16_emitcode("inc","dptr");
8880             pic16_emitcode("lcall","__gptrget");
8881             break;
8882         }
8883
8884         rlen -= 8;            
8885         /* if we are done */
8886         if ( rlen <= 0 )
8887             break ;
8888         
8889         pic16_aopPut(AOP(result),"a",offset++);
8890                               
8891     }
8892     
8893     if (rlen) {
8894         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8895         pic16_aopPut(AOP(result),"a",offset);          
8896     }
8897     
8898     return ;
8899 }
8900
8901
8902 static void genDataPointerGet(operand *left,
8903                               operand *result,
8904                               iCode *ic)
8905 {
8906   int size, offset = 0, leoffset=0 ;
8907
8908         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8909         pic16_aopOp(result, ic, FALSE);
8910
8911         size = AOP_SIZE(result);
8912 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8913
8914
8915 #if 0
8916         /* The following tests may save a redudant movff instruction when
8917          * accessing unions */
8918          
8919         /* if they are the same */
8920         if (operandsEqu (left, result)) {
8921                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
8922                 goto release;
8923         }
8924 #endif
8925
8926 #if 0
8927         /* if they are the same registers */
8928         if (pic16_sameRegs(AOP(left),AOP(result))) {
8929                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
8930                 goto release;
8931         }
8932 #endif
8933
8934 #if 0
8935         if ( AOP_TYPE(left) == AOP_PCODE) {
8936                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
8937                                 AOP(left)->aopu.pcop->name,
8938                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
8939                                 PCOR(AOP(left)->aopu.pcop)->instance:
8940                                 PCOI(AOP(left)->aopu.pcop)->offset);
8941         }
8942 #endif
8943
8944         if(AOP(left)->aopu.pcop->type == PO_DIR)
8945                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8946
8947         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8948
8949         while (size--) {
8950                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8951                 
8952                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
8953                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
8954                         mov2w(AOP(left), offset); // patch 8
8955                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8956                 } else {
8957                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8958                                 pic16_popGet(AOP(left), offset), //patch 8
8959                                 pic16_popGet(AOP(result), offset)));
8960                 }
8961
8962                 offset++;
8963                 leoffset++;
8964         }
8965
8966 //release:
8967     pic16_freeAsmop(result,NULL,ic,TRUE);
8968 }
8969
8970 void pic16_loadFSR0(operand *op)
8971 {
8972         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
8973 }
8974
8975
8976 /*-----------------------------------------------------------------*/
8977 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8978 /*-----------------------------------------------------------------*/
8979 static void genNearPointerGet (operand *left, 
8980                                operand *result, 
8981                                iCode *ic)
8982 {
8983     asmop *aop = NULL;
8984     //regs *preg = NULL ;
8985     sym_link *rtype, *retype;
8986     sym_link *ltype = operandType(left);    
8987
8988         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8989         rtype = operandType(result);
8990         retype= getSpec(rtype);
8991     
8992         pic16_aopOp(left,ic,FALSE);
8993
8994         pic16_DumpOp("(left)",left);
8995         pic16_DumpOp("(result)",result);
8996
8997         /* if left is rematerialisable and
8998          * result is not bit variable type and
8999          * the left is pointer to data space i.e
9000          * lower 128 bytes of space */
9001         if (AOP_TYPE(left) == AOP_PCODE
9002                 && !IS_BITFIELD(retype)
9003                 && DCL_TYPE(ltype) == POINTER) {
9004
9005                 genDataPointerGet (left,result,ic);
9006                 pic16_freeAsmop(left, NULL, ic, TRUE);
9007           return ;
9008         }
9009     
9010         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9011
9012         /* if the value is already in a pointer register
9013          * then don't need anything more */
9014         if (!AOP_INPREG(AOP(left))) {
9015                 /* otherwise get a free pointer register */
9016                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9017                 
9018                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9019                 if( (AOP_TYPE(left) == AOP_PCODE) 
9020                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9021                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9022                 {
9023                         pic16_loadFSR0( left );  // patch 10
9024                 } else {
9025                         // set up FSR0 with address from left
9026                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9027                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9028                 }
9029         }
9030 //       else
9031 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9032     
9033         pic16_aopOp (result,ic,FALSE);
9034     
9035       /* if bitfield then unpack the bits */
9036     if (IS_BITFIELD(retype)) 
9037         genUnpackBits (result, NULL, POINTER);
9038     else {
9039         /* we have can just get the values */
9040       int size = AOP_SIZE(result);
9041       int offset = 0;   
9042         
9043       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9044
9045
9046         /* fsr0 is loaded already -- VR */
9047 //      pic16_loadFSR0( left );
9048
9049 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9050 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9051       while(size--) {
9052
9053         if(size) {
9054                 pic16_emitpcode(POC_MOVFF,
9055                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9056                                 pic16_popGet(AOP(result), offset++)));
9057         } else {
9058                 pic16_emitpcode(POC_MOVFF,
9059                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9060                                 pic16_popGet(AOP(result), offset++)));
9061         }
9062       }
9063 #if 0
9064 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9065 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9066         if(size)
9067           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9068 #endif
9069 /*
9070         while (size--) {
9071             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9072
9073                 pic16_emitcode("mov","a,@%s",rname);
9074                 pic16_aopPut(AOP(result),"a",offset);
9075             } else {
9076                 sprintf(buffer,"@%s",rname);
9077                 pic16_aopPut(AOP(result),buffer,offset);
9078             }
9079             offset++ ;
9080             if (size)
9081                 pic16_emitcode("inc","%s",rname);
9082         }
9083 */
9084     }
9085
9086     /* now some housekeeping stuff */
9087     if (aop) {
9088         /* we had to allocate for this iCode */
9089     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9090         pic16_freeAsmop(NULL,aop,ic,TRUE);
9091     } else { 
9092         /* we did not allocate which means left
9093            already in a pointer register, then
9094            if size > 0 && this could be used again
9095            we have to point it back to where it 
9096            belongs */
9097     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9098         if (AOP_SIZE(result) > 1 &&
9099             !OP_SYMBOL(left)->remat &&
9100             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9101               ic->depth )) {
9102 //          int size = AOP_SIZE(result) - 1;
9103 //          while (size--)
9104 //              pic16_emitcode("dec","%s",rname);
9105         }
9106     }
9107
9108     /* done */
9109     pic16_freeAsmop(left,NULL,ic,TRUE);
9110     pic16_freeAsmop(result,NULL,ic,TRUE);
9111      
9112 }
9113
9114 /*-----------------------------------------------------------------*/
9115 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9116 /*-----------------------------------------------------------------*/
9117 static void genPagedPointerGet (operand *left, 
9118                                operand *result, 
9119                                iCode *ic)
9120 {
9121     asmop *aop = NULL;
9122     regs *preg = NULL ;
9123     char *rname ;
9124     sym_link *rtype, *retype;    
9125
9126     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9127
9128     rtype = operandType(result);
9129     retype= getSpec(rtype);
9130     
9131     pic16_aopOp(left,ic,FALSE);
9132
9133   /* if the value is already in a pointer register
9134        then don't need anything more */
9135     if (!AOP_INPREG(AOP(left))) {
9136         /* otherwise get a free pointer register */
9137         aop = newAsmop(0);
9138         preg = getFreePtr(ic,&aop,FALSE);
9139         pic16_emitcode("mov","%s,%s",
9140                 preg->name,
9141                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9142         rname = preg->name ;
9143     } else
9144         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9145     
9146     pic16_freeAsmop(left,NULL,ic,TRUE);
9147     pic16_aopOp (result,ic,FALSE);
9148
9149     /* if bitfield then unpack the bits */
9150     if (IS_BITFIELD(retype)) 
9151         genUnpackBits (result,rname,PPOINTER);
9152     else {
9153         /* we have can just get the values */
9154         int size = AOP_SIZE(result);
9155         int offset = 0 ;        
9156         
9157         while (size--) {
9158             
9159             pic16_emitcode("movx","a,@%s",rname);
9160             pic16_aopPut(AOP(result),"a",offset);
9161             
9162             offset++ ;
9163             
9164             if (size)
9165                 pic16_emitcode("inc","%s",rname);
9166         }
9167     }
9168
9169     /* now some housekeeping stuff */
9170     if (aop) {
9171         /* we had to allocate for this iCode */
9172         pic16_freeAsmop(NULL,aop,ic,TRUE);
9173     } else { 
9174         /* we did not allocate which means left
9175            already in a pointer register, then
9176            if size > 0 && this could be used again
9177            we have to point it back to where it 
9178            belongs */
9179         if (AOP_SIZE(result) > 1 &&
9180             !OP_SYMBOL(left)->remat &&
9181             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9182               ic->depth )) {
9183             int size = AOP_SIZE(result) - 1;
9184             while (size--)
9185                 pic16_emitcode("dec","%s",rname);
9186         }
9187     }
9188
9189     /* done */
9190     pic16_freeAsmop(result,NULL,ic,TRUE);
9191     
9192         
9193 }
9194
9195 /*-----------------------------------------------------------------*/
9196 /* genFarPointerGet - gget value from far space                    */
9197 /*-----------------------------------------------------------------*/
9198 static void genFarPointerGet (operand *left,
9199                               operand *result, iCode *ic)
9200 {
9201     int size, offset ;
9202     sym_link *retype = getSpec(operandType(result));
9203
9204     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9205
9206     pic16_aopOp(left,ic,FALSE);
9207
9208     /* if the operand is already in dptr 
9209     then we do nothing else we move the value to dptr */
9210     if (AOP_TYPE(left) != AOP_STR) {
9211         /* if this is remateriazable */
9212         if (AOP_TYPE(left) == AOP_IMMD)
9213             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9214         else { /* we need to get it byte by byte */
9215             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9216             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9217             if (options.model == MODEL_FLAT24)
9218             {
9219                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9220             }
9221         }
9222     }
9223     /* so dptr know contains the address */
9224     pic16_freeAsmop(left,NULL,ic,TRUE);
9225     pic16_aopOp(result,ic,FALSE);
9226
9227     /* if bit then unpack */
9228     if (IS_BITFIELD(retype)) 
9229         genUnpackBits(result,"dptr",FPOINTER);
9230     else {
9231         size = AOP_SIZE(result);
9232         offset = 0 ;
9233
9234         while (size--) {
9235             pic16_emitcode("movx","a,@dptr");
9236             pic16_aopPut(AOP(result),"a",offset++);
9237             if (size)
9238                 pic16_emitcode("inc","dptr");
9239         }
9240     }
9241
9242     pic16_freeAsmop(result,NULL,ic,TRUE);
9243 }
9244 #if 0
9245 /*-----------------------------------------------------------------*/
9246 /* genCodePointerGet - get value from code space                  */
9247 /*-----------------------------------------------------------------*/
9248 static void genCodePointerGet (operand *left,
9249                                 operand *result, iCode *ic)
9250 {
9251     int size, offset ;
9252     sym_link *retype = getSpec(operandType(result));
9253
9254     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9255
9256     pic16_aopOp(left,ic,FALSE);
9257
9258     /* if the operand is already in dptr 
9259     then we do nothing else we move the value to dptr */
9260     if (AOP_TYPE(left) != AOP_STR) {
9261         /* if this is remateriazable */
9262         if (AOP_TYPE(left) == AOP_IMMD)
9263             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9264         else { /* we need to get it byte by byte */
9265             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9266             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9267             if (options.model == MODEL_FLAT24)
9268             {
9269                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9270             }
9271         }
9272     }
9273     /* so dptr know contains the address */
9274     pic16_freeAsmop(left,NULL,ic,TRUE);
9275     pic16_aopOp(result,ic,FALSE);
9276
9277     /* if bit then unpack */
9278     if (IS_BITFIELD(retype)) 
9279         genUnpackBits(result,"dptr",CPOINTER);
9280     else {
9281         size = AOP_SIZE(result);
9282         offset = 0 ;
9283
9284         while (size--) {
9285             pic16_emitcode("clr","a");
9286             pic16_emitcode("movc","a,@a+dptr");
9287             pic16_aopPut(AOP(result),"a",offset++);
9288             if (size)
9289                 pic16_emitcode("inc","dptr");
9290         }
9291     }
9292
9293     pic16_freeAsmop(result,NULL,ic,TRUE);
9294 }
9295 #endif
9296 /*-----------------------------------------------------------------*/
9297 /* genGenPointerGet - gget value from generic pointer space        */
9298 /*-----------------------------------------------------------------*/
9299 static void genGenPointerGet (operand *left,
9300                               operand *result, iCode *ic)
9301 {
9302   int size, offset, lit;
9303   sym_link *retype = getSpec(operandType(result));
9304
9305         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9306         pic16_aopOp(left,ic,FALSE);
9307         pic16_aopOp(result,ic,FALSE);
9308         size = AOP_SIZE(result);
9309
9310         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9311
9312         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9313
9314                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9315                 // load FSR0 from immediate
9316                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9317
9318 //              pic16_loadFSR0( left );
9319
9320                 offset = 0;
9321                 while(size--) {
9322                         if(size) {
9323                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9324                         } else {
9325                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9326                         }
9327                         offset++;
9328                 }
9329                 goto release;
9330
9331         }
9332         else { /* we need to get it byte by byte */
9333                 // set up FSR0 with address from left
9334                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9335                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9336
9337                 offset = 0 ;
9338
9339                 while(size--) {
9340                         if(size) {
9341                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9342                         } else {
9343                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9344                         }
9345                         offset++;
9346                 }
9347                 goto release;
9348         }
9349
9350   /* if bit then unpack */
9351         if (IS_BITFIELD(retype)) 
9352                 genUnpackBits(result,"BAD",GPOINTER);
9353
9354         release:
9355         pic16_freeAsmop(left,NULL,ic,TRUE);
9356         pic16_freeAsmop(result,NULL,ic,TRUE);
9357
9358 }
9359
9360 /*-----------------------------------------------------------------*/
9361 /* genConstPointerGet - get value from const generic pointer space */
9362 /*-----------------------------------------------------------------*/
9363 static void genConstPointerGet (operand *left,
9364                                 operand *result, iCode *ic)
9365 {
9366   //sym_link *retype = getSpec(operandType(result));
9367   // symbol *albl = newiTempLabel(NULL);        // patch 15
9368   // symbol *blbl = newiTempLabel(NULL);        //
9369   // PIC_OPCODE poc;                            // patch 15
9370   int size;
9371   int offset = 0;
9372
9373   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9374   pic16_aopOp(left,ic,FALSE);
9375   pic16_aopOp(result,ic,TRUE);
9376   size = AOP_SIZE(result);
9377
9378   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9379
9380   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9381 #if 0                                                                   // patch 15
9382   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9383   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9384   pic16_emitpLabel(albl->key);
9385
9386   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9387     
9388   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9389   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9390   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9391   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9392   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9393
9394   pic16_emitpLabel(blbl->key);
9395
9396   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9397 #endif                                                                  // patch 15
9398
9399
9400   // set up table pointer
9401   if( (AOP_TYPE(left) == AOP_PCODE) 
9402       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9403           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9404     {
9405       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9406       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9407       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9408       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9409       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9410       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9411     }
9412   else
9413     {
9414       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9415       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9416       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9417     }
9418
9419
9420   while(size--)
9421     {
9422       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9423       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9424       offset++;
9425     }
9426                                                                         // .... patch 15
9427   pic16_freeAsmop(left,NULL,ic,TRUE);
9428   pic16_freeAsmop(result,NULL,ic,TRUE);
9429
9430 }
9431 /*-----------------------------------------------------------------*/
9432 /* genPointerGet - generate code for pointer get                   */
9433 /*-----------------------------------------------------------------*/
9434 static void genPointerGet (iCode *ic)
9435 {
9436     operand *left, *result ;
9437     sym_link *type, *etype;
9438     int p_type;
9439
9440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9441
9442     left = IC_LEFT(ic);
9443     result = IC_RESULT(ic) ;
9444
9445     /* depending on the type of pointer we need to
9446     move it to the correct pointer register */
9447     type = operandType(left);
9448     etype = getSpec(type);
9449
9450 #if 0
9451     if (IS_PTR_CONST(type))
9452 #else
9453     if (IS_CODEPTR(type))
9454 #endif
9455       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9456
9457     /* if left is of type of pointer then it is simple */
9458     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9459         p_type = DCL_TYPE(type);
9460     else {
9461         /* we have to go by the storage class */
9462         p_type = PTR_TYPE(SPEC_OCLS(etype));
9463
9464         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9465
9466         if (SPEC_OCLS(etype)->codesp ) {
9467           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9468           //p_type = CPOINTER ; 
9469         }
9470         else
9471             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9472               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9473                /*p_type = FPOINTER ;*/ 
9474             else
9475                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9476                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9477 /*                  p_type = PPOINTER; */
9478                 else
9479                     if (SPEC_OCLS(etype) == idata )
9480                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9481 /*                      p_type = IPOINTER; */
9482                     else
9483                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9484 /*                      p_type = POINTER ; */
9485     }
9486
9487     /* now that we have the pointer type we assign
9488     the pointer values */
9489     switch (p_type) {
9490
9491     case POINTER:       
9492     case IPOINTER:
9493         genNearPointerGet (left,result,ic);
9494         break;
9495
9496     case PPOINTER:
9497         genPagedPointerGet(left,result,ic);
9498         break;
9499
9500     case FPOINTER:
9501         genFarPointerGet (left,result,ic);
9502         break;
9503
9504     case CPOINTER:
9505         genConstPointerGet (left,result,ic);
9506         //pic16_emitcodePointerGet (left,result,ic);
9507         break;
9508
9509     case GPOINTER:
9510 #if 0
9511       if (IS_PTR_CONST(type))
9512         genConstPointerGet (left,result,ic);
9513       else
9514 #endif
9515         genGenPointerGet (left,result,ic);
9516       break;
9517     }
9518
9519 }
9520
9521 /*-----------------------------------------------------------------*/
9522 /* genPackBits - generates code for packed bit storage             */
9523 /*-----------------------------------------------------------------*/
9524 static void genPackBits (sym_link    *etype ,
9525                          operand *right ,
9526                          char *rname, int p_type)
9527 {
9528   int shCnt = 0 ;
9529   int offset = 0  ;
9530   int rLen = 0 ;
9531   int blen, bstr ;   
9532   char *l ;
9533
9534         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9535         blen = SPEC_BLEN(etype);
9536         bstr = SPEC_BSTR(etype);
9537
9538         if(AOP_TYPE(right) == AOP_LIT) {
9539                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9540                 offset++;
9541         } else
9542                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9543
9544 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9545         MOVA(l);   
9546 */
9547         /* if the bit lenth is less than or    */
9548         /* it exactly fits a byte then         */
9549         if((shCnt=SPEC_BSTR(etype))
9550                 || SPEC_BLEN(etype) <= 8 )  {
9551
9552                 /* shift left acc */
9553                 AccLsh(shCnt);
9554
9555                 /* using PRODL as a temporary register here */
9556                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9557
9558                 switch (p_type) {
9559                         case FPOINTER:
9560                         case POINTER:
9561                         case GPOINTER:
9562                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9563 //                              pic16_emitcode ("mov","b,a");
9564 //                              pic16_emitcode("mov","a,@%s",rname);
9565                                 break;
9566                 }
9567 #if 1
9568                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9569                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9570                                         (unsigned char)(0xff >> (8-bstr))) ));
9571                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9572                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9573 #endif
9574
9575 #if 0
9576                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9577                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9578                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9579                 pic16_emitcode ("orl","a,b");
9580                 if (p_type == GPOINTER)
9581                         pic16_emitcode("pop","b");
9582
9583                 
9584                 switch (p_type) {
9585                         case POINTER:
9586                                 pic16_emitcode("mov","@%s,a",rname);
9587                                 break;
9588                         case FPOINTER:
9589                                 pic16_emitcode("movx","@dptr,a");
9590                                 break;
9591                         case GPOINTER:
9592                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9593                                 break;
9594                 }
9595 #endif
9596
9597           return;
9598         }
9599
9600
9601         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9602         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9603         exit(-1);
9604
9605
9606     /* if we r done */
9607     if ( SPEC_BLEN(etype) <= 8 )
9608         return ;
9609
9610     pic16_emitcode("inc","%s",rname);
9611     rLen = SPEC_BLEN(etype) ;     
9612
9613
9614
9615     /* now generate for lengths greater than one byte */
9616     while (1) {
9617
9618         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9619
9620         rLen -= 8 ;
9621         if (rLen <= 0 )
9622             break ;
9623
9624         switch (p_type) {
9625             case POINTER:
9626                 if (*l == '@') {
9627                     MOVA(l);
9628                     pic16_emitcode("mov","@%s,a",rname);
9629                 } else
9630                     pic16_emitcode("mov","@%s,%s",rname,l);
9631                 break;
9632
9633             case FPOINTER:
9634                 MOVA(l);
9635                 pic16_emitcode("movx","@dptr,a");
9636                 break;
9637
9638             case GPOINTER:
9639                 MOVA(l);
9640                 DEBUGpic16_emitcode(";lcall","__gptrput");
9641                 break;  
9642         }   
9643         pic16_emitcode ("inc","%s",rname);
9644     }
9645
9646     MOVA(l);
9647
9648     /* last last was not complete */
9649     if (rLen)   {
9650         /* save the byte & read byte */
9651         switch (p_type) {
9652             case POINTER:
9653                 pic16_emitcode ("mov","b,a");
9654                 pic16_emitcode("mov","a,@%s",rname);
9655                 break;
9656
9657             case FPOINTER:
9658                 pic16_emitcode ("mov","b,a");
9659                 pic16_emitcode("movx","a,@dptr");
9660                 break;
9661
9662             case GPOINTER:
9663                 pic16_emitcode ("push","b");
9664                 pic16_emitcode ("push","acc");
9665                 pic16_emitcode ("lcall","__gptrget");
9666                 pic16_emitcode ("pop","b");
9667                 break;
9668         }
9669
9670         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9671         pic16_emitcode ("orl","a,b");
9672     }
9673
9674     if (p_type == GPOINTER)
9675         pic16_emitcode("pop","b");
9676
9677     switch (p_type) {
9678
9679     case POINTER:
9680         pic16_emitcode("mov","@%s,a",rname);
9681         break;
9682         
9683     case FPOINTER:
9684         pic16_emitcode("movx","@dptr,a");
9685         break;
9686         
9687     case GPOINTER:
9688         DEBUGpic16_emitcode(";lcall","__gptrput");
9689         break;                  
9690     }
9691 }
9692 /*-----------------------------------------------------------------*/
9693 /* genDataPointerSet - remat pointer to data space                 */
9694 /*-----------------------------------------------------------------*/
9695 static void genDataPointerSet(operand *right,
9696                               operand *result,
9697                               iCode *ic)
9698 {
9699     int size, offset = 0, resoffset=0 ;
9700
9701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9702     pic16_aopOp(right,ic,FALSE);
9703
9704     size = AOP_SIZE(right);
9705
9706 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9707
9708 #if 0
9709     if ( AOP_TYPE(result) == AOP_PCODE) {
9710       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9711               AOP(result)->aopu.pcop->name,
9712                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9713               PCOR(AOP(result)->aopu.pcop)->instance:
9714               PCOI(AOP(result)->aopu.pcop)->offset);
9715     }
9716 #endif
9717
9718         if(AOP(result)->aopu.pcop->type == PO_DIR)
9719                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9720
9721         while (size--) {
9722                 if (AOP_TYPE(right) == AOP_LIT) {
9723                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9724
9725                         lit = lit >> (8*offset);
9726                         if(lit&0xff) {
9727                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9728                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9729                         } else {
9730                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9731                         }
9732                 } else {
9733                         mov2w(AOP(right), offset);
9734                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9735                 }
9736                 offset++;
9737                 resoffset++;
9738         }
9739
9740     pic16_freeAsmop(right,NULL,ic,TRUE);
9741 }
9742
9743
9744
9745 /*-----------------------------------------------------------------*/
9746 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9747 /*-----------------------------------------------------------------*/
9748 static void genNearPointerSet (operand *right,
9749                                operand *result, 
9750                                iCode *ic)
9751 {
9752   asmop *aop = NULL;
9753   char *l;
9754   sym_link *retype;
9755   sym_link *ptype = operandType(result);
9756   sym_link *resetype;
9757     
9758         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9759         retype= getSpec(operandType(right));
9760         resetype = getSpec(operandType(result));
9761   
9762         pic16_aopOp(result,ic,FALSE);
9763     
9764         /* if the result is rematerializable &
9765          * in data space & not a bit variable */
9766         
9767         /* and result is not a bit variable */
9768         if (AOP_TYPE(result) == AOP_PCODE
9769 //              && AOP_TYPE(result) == AOP_IMMD
9770                 && DCL_TYPE(ptype) == POINTER
9771                 && !IS_BITFIELD(retype)
9772                 && !IS_BITFIELD(resetype)) {
9773
9774                 genDataPointerSet (right,result,ic);
9775                 pic16_freeAsmop(result,NULL,ic,TRUE);
9776           return;
9777         }
9778
9779         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9780         pic16_aopOp(right,ic,FALSE);
9781         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9782
9783         /* if the value is already in a pointer register
9784          * then don't need anything more */
9785         if (!AOP_INPREG(AOP(result))) {
9786                 /* otherwise get a free pointer register */
9787                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9788
9789                 if( (AOP_TYPE(result) == AOP_PCODE) 
9790                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9791                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9792                 {
9793                         pic16_loadFSR0( result );  // patch 10
9794                 } else {
9795                         // set up FSR0 with address of result
9796                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9797                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9798                 }
9799
9800         }
9801 //      else
9802 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9803
9804         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9805
9806         /* if bitfield then unpack the bits */
9807         if (IS_BITFIELD(resetype)) {
9808                 genPackBits (resetype, right, NULL, POINTER);
9809         } else {
9810                 /* we have can just get the values */
9811           int size = AOP_SIZE(right);
9812           int offset = 0 ;    
9813
9814                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9815                 while (size--) {
9816                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9817                         if (*l == '@' ) {
9818                                 //MOVA(l);
9819                                 //pic16_emitcode("mov","@%s,a",rname);
9820                                 pic16_emitcode("movf","indf0,w ;1");
9821                         } else {
9822
9823                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9824                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9825                                         if (size) {                                                                     // 
9826                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9827                                         } else {                                                                        // 
9828                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9829                                         }                                                                               // 
9830                                 } else { // no literal                                                                  // 
9831                                         if(size) {                                                                      // 
9832                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9833                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9834                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9835                                         } else {                                                                        // 
9836                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9837                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9838                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9839                                         }                                                                               //
9840                                 }                                                                                       // patch 10
9841                         }
9842                         offset++;
9843                 }
9844         }
9845
9846         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9847         /* now some housekeeping stuff */
9848         if (aop) {
9849                 /* we had to allocate for this iCode */
9850                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9851         } else { 
9852                 /* we did not allocate which means left
9853                  * already in a pointer register, then
9854                  * if size > 0 && this could be used again
9855                  * we have to point it back to where it 
9856                  * belongs */
9857                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9858                 if (AOP_SIZE(right) > 1
9859                         && !OP_SYMBOL(result)->remat
9860                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9861                                 || ic->depth )) {
9862
9863                   int size = AOP_SIZE(right) - 1;
9864
9865                         while (size--)
9866                                 pic16_emitcode("decf","fsr0,f");
9867                         //pic16_emitcode("dec","%s",rname);
9868                 }
9869         }
9870
9871         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9872         /* done */
9873 //release:
9874         pic16_freeAsmop(right,NULL,ic,TRUE);
9875         pic16_freeAsmop(result,NULL,ic,TRUE);
9876 }
9877
9878 /*-----------------------------------------------------------------*/
9879 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9880 /*-----------------------------------------------------------------*/
9881 static void genPagedPointerSet (operand *right,
9882                                operand *result, 
9883                                iCode *ic)
9884 {
9885     asmop *aop = NULL;
9886     regs *preg = NULL ;
9887     char *rname , *l;
9888     sym_link *retype;
9889        
9890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9891
9892     retype= getSpec(operandType(right));
9893     
9894     pic16_aopOp(result,ic,FALSE);
9895     
9896     /* if the value is already in a pointer register
9897        then don't need anything more */
9898     if (!AOP_INPREG(AOP(result))) {
9899         /* otherwise get a free pointer register */
9900         aop = newAsmop(0);
9901         preg = getFreePtr(ic,&aop,FALSE);
9902         pic16_emitcode("mov","%s,%s",
9903                 preg->name,
9904                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9905         rname = preg->name ;
9906     } else
9907         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9908     
9909     pic16_freeAsmop(result,NULL,ic,TRUE);
9910     pic16_aopOp (right,ic,FALSE);
9911
9912     /* if bitfield then unpack the bits */
9913     if (IS_BITFIELD(retype)) 
9914         genPackBits (retype,right,rname,PPOINTER);
9915     else {
9916         /* we have can just get the values */
9917         int size = AOP_SIZE(right);
9918         int offset = 0 ;        
9919         
9920         while (size--) {
9921             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9922             
9923             MOVA(l);
9924             pic16_emitcode("movx","@%s,a",rname);
9925
9926             if (size)
9927                 pic16_emitcode("inc","%s",rname);
9928
9929             offset++;
9930         }
9931     }
9932     
9933     /* now some housekeeping stuff */
9934     if (aop) {
9935         /* we had to allocate for this iCode */
9936         pic16_freeAsmop(NULL,aop,ic,TRUE);
9937     } else { 
9938         /* we did not allocate which means left
9939            already in a pointer register, then
9940            if size > 0 && this could be used again
9941            we have to point it back to where it 
9942            belongs */
9943         if (AOP_SIZE(right) > 1 &&
9944             !OP_SYMBOL(result)->remat &&
9945             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9946               ic->depth )) {
9947             int size = AOP_SIZE(right) - 1;
9948             while (size--)
9949                 pic16_emitcode("dec","%s",rname);
9950         }
9951     }
9952
9953     /* done */
9954     pic16_freeAsmop(right,NULL,ic,TRUE);
9955     
9956         
9957 }
9958
9959 /*-----------------------------------------------------------------*/
9960 /* genFarPointerSet - set value from far space                     */
9961 /*-----------------------------------------------------------------*/
9962 static void genFarPointerSet (operand *right,
9963                               operand *result, iCode *ic)
9964 {
9965     int size, offset ;
9966     sym_link *retype = getSpec(operandType(right));
9967
9968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9969     pic16_aopOp(result,ic,FALSE);
9970
9971     /* if the operand is already in dptr 
9972     then we do nothing else we move the value to dptr */
9973     if (AOP_TYPE(result) != AOP_STR) {
9974         /* if this is remateriazable */
9975         if (AOP_TYPE(result) == AOP_IMMD)
9976             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9977         else { /* we need to get it byte by byte */
9978             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9979             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9980             if (options.model == MODEL_FLAT24)
9981             {
9982                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9983             }
9984         }
9985     }
9986     /* so dptr know contains the address */
9987     pic16_freeAsmop(result,NULL,ic,TRUE);
9988     pic16_aopOp(right,ic,FALSE);
9989
9990     /* if bit then unpack */
9991     if (IS_BITFIELD(retype)) 
9992         genPackBits(retype,right,"dptr",FPOINTER);
9993     else {
9994         size = AOP_SIZE(right);
9995         offset = 0 ;
9996
9997         while (size--) {
9998             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9999             MOVA(l);
10000             pic16_emitcode("movx","@dptr,a");
10001             if (size)
10002                 pic16_emitcode("inc","dptr");
10003         }
10004     }
10005
10006     pic16_freeAsmop(right,NULL,ic,TRUE);
10007 }
10008
10009 /*-----------------------------------------------------------------*/
10010 /* genGenPointerSet - set value from generic pointer space         */
10011 /*-----------------------------------------------------------------*/
10012 static void genGenPointerSet (operand *right,
10013                               operand *result, iCode *ic)
10014 {
10015         int i, size, offset, lit;
10016         sym_link *retype = getSpec(operandType(right));
10017
10018         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10019
10020         pic16_aopOp(result,ic,FALSE);
10021         pic16_aopOp(right,ic,FALSE);
10022         size = AOP_SIZE(right);
10023         offset = 0;
10024
10025         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10026
10027         /* if the operand is already in dptr 
10028                 then we do nothing else we move the value to dptr */
10029         if (AOP_TYPE(result) != AOP_STR) {
10030                 /* if this is remateriazable */
10031                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10032                 // WARNING: anythig until "else" is untested!
10033                 if (AOP_TYPE(result) == AOP_IMMD) {
10034                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10035                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10036                         // load FSR0 from immediate
10037                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10038                         offset = 0;
10039                         while(size--) {
10040                                 if(size) {
10041                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10042                                 } else {
10043                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10044                                 }
10045                                 offset++;
10046                         }
10047                         goto release;
10048                 }
10049                 else { /* we need to get it byte by byte */
10050                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10051                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10052
10053                         // set up FSR0 with address of result
10054                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10055                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10056
10057                         /* hack hack! see if this the FSR. If so don't load W */
10058                         if(AOP_TYPE(right) != AOP_ACC) {
10059
10060                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10061
10062                                 if(AOP_TYPE(right) == AOP_LIT)
10063                                 {
10064                                         // copy literal
10065                                         // note: pic16_popGet handles sign extension
10066                                         for(i=0;i<size;i++) {
10067                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10068                                                 if(i < size-1)
10069                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10070                                                 else
10071                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10072                                         }
10073                                 } else {
10074                                         // copy regs
10075
10076                                         for(i=0;i<size;i++) {
10077                                                 if(i < size-1)
10078                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10079                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10080                                                 else
10081                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10082                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10083                                         }
10084                                 }
10085                                 goto release;
10086                         } 
10087                         // right = ACC
10088                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10089                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10090                         goto release;
10091         } // if (AOP_TYPE(result) != AOP_IMMD)
10092
10093         } // if (AOP_TYPE(result) != AOP_STR)
10094         /* so dptr know contains the address */
10095
10096
10097         /* if bit then unpack */
10098         if (IS_BITFIELD(retype)) 
10099                 genPackBits(retype,right,"dptr",GPOINTER);
10100         else {
10101                 size = AOP_SIZE(right);
10102                 offset = 0 ;
10103
10104                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10105
10106                 // set up FSR0 with address of result
10107                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10108                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10109         
10110                 while (size--) {
10111                         if (AOP_TYPE(right) == AOP_LIT) {
10112                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10113                                 if (size) {
10114                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10115                                 } else {
10116                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10117                                 }
10118                         } else { // no literal
10119                                 if(size) {
10120                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10121                                 } else {
10122                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10123                                 }
10124                         }
10125                         offset++;
10126                 }
10127         }
10128
10129         release:
10130         pic16_freeAsmop(right,NULL,ic,TRUE);
10131         pic16_freeAsmop(result,NULL,ic,TRUE);
10132 }
10133
10134 /*-----------------------------------------------------------------*/
10135 /* genPointerSet - stores the value into a pointer location        */
10136 /*-----------------------------------------------------------------*/
10137 static void genPointerSet (iCode *ic)
10138 {    
10139     operand *right, *result ;
10140     sym_link *type, *etype;
10141     int p_type;
10142
10143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10144
10145     right = IC_RIGHT(ic);
10146     result = IC_RESULT(ic) ;
10147
10148     /* depending on the type of pointer we need to
10149     move it to the correct pointer register */
10150     type = operandType(result);
10151     etype = getSpec(type);
10152     /* if left is of type of pointer then it is simple */
10153     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10154         p_type = DCL_TYPE(type);
10155     }
10156     else {
10157         /* we have to go by the storage class */
10158         p_type = PTR_TYPE(SPEC_OCLS(etype));
10159
10160 /*      if (SPEC_OCLS(etype)->codesp ) { */
10161 /*          p_type = CPOINTER ;  */
10162 /*      } */
10163 /*      else */
10164 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10165 /*              p_type = FPOINTER ; */
10166 /*          else */
10167 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10168 /*                  p_type = PPOINTER ; */
10169 /*              else */
10170 /*                  if (SPEC_OCLS(etype) == idata ) */
10171 /*                      p_type = IPOINTER ; */
10172 /*                  else */
10173 /*                      p_type = POINTER ; */
10174     }
10175
10176     /* now that we have the pointer type we assign
10177     the pointer values */
10178     switch (p_type) {
10179
10180     case POINTER:
10181     case IPOINTER:
10182         genNearPointerSet (right,result,ic);
10183         break;
10184
10185     case PPOINTER:
10186         genPagedPointerSet (right,result,ic);
10187         break;
10188
10189     case FPOINTER:
10190         genFarPointerSet (right,result,ic);
10191         break;
10192
10193     case GPOINTER:
10194         genGenPointerSet (right,result,ic);
10195         break;
10196
10197     default:
10198       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10199               "genPointerSet: illegal pointer type");
10200     }
10201 }
10202
10203 /*-----------------------------------------------------------------*/
10204 /* genIfx - generate code for Ifx statement                        */
10205 /*-----------------------------------------------------------------*/
10206 static void genIfx (iCode *ic, iCode *popIc)
10207 {
10208   operand *cond = IC_COND(ic);
10209   int isbit =0;
10210
10211   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10212
10213   pic16_aopOp(cond,ic,FALSE);
10214
10215   /* get the value into acc */
10216   if (AOP_TYPE(cond) != AOP_CRY)
10217     pic16_toBoolean(cond);
10218   else
10219     isbit = 1;
10220   /* the result is now in the accumulator */
10221   pic16_freeAsmop(cond,NULL,ic,TRUE);
10222
10223   /* if there was something to be popped then do it */
10224   if (popIc)
10225     genIpop(popIc);
10226
10227   /* if the condition is  a bit variable */
10228   if (isbit && IS_ITEMP(cond) && 
10229       SPIL_LOC(cond)) {
10230     genIfxJump(ic,SPIL_LOC(cond)->rname);
10231     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10232   }
10233   else {
10234     if (isbit && !IS_ITEMP(cond))
10235       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10236     else
10237       genIfxJump(ic,"a");
10238   }
10239   ic->generated = 1;
10240
10241 }
10242
10243 /*-----------------------------------------------------------------*/
10244 /* genAddrOf - generates code for address of                       */
10245 /*-----------------------------------------------------------------*/
10246 static void genAddrOf (iCode *ic)
10247 {
10248   operand *result, *left;
10249   int size;
10250   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10251   pCodeOp *pcop0, *pcop1, *pcop2;
10252
10253         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10254
10255         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10256         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10257
10258         sym = OP_SYMBOL( left );
10259
10260         size = AOP_SIZE(IC_RESULT(ic));
10261
10262         if(pic16_debug_verbose) {
10263                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10264                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10265         }
10266         
10267         /* Assume that what we want the address of is in data space
10268          * since there is no stack on the PIC, yet! -- VR */
10269         /* low */
10270         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10271
10272         /* high */
10273         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10274         
10275         /* upper */
10276         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10277         
10278
10279         if (size == 3) {
10280                 pic16_emitpcode(POC_MOVLW, pcop0);
10281                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10282                 pic16_emitpcode(POC_MOVLW, pcop1);
10283                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10284                 pic16_emitpcode(POC_MOVLW, pcop2);
10285                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10286         } else
10287         if (size == 2) {
10288                 pic16_emitpcode(POC_MOVLW, pcop0);
10289                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10290                 pic16_emitpcode(POC_MOVLW, pcop1);
10291                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10292         } else {
10293                 pic16_emitpcode(POC_MOVLW, pcop0);
10294                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10295         }
10296
10297         pic16_freeAsmop(result,NULL,ic,TRUE);
10298         pic16_freeAsmop(left, NULL, ic, FALSE);
10299 }
10300
10301
10302 #if 0
10303 /*-----------------------------------------------------------------*/
10304 /* genFarFarAssign - assignment when both are in far space         */
10305 /*-----------------------------------------------------------------*/
10306 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10307 {
10308     int size = AOP_SIZE(right);
10309     int offset = 0;
10310     char *l ;
10311     /* first push the right side on to the stack */
10312     while (size--) {
10313         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10314         MOVA(l);
10315         pic16_emitcode ("push","acc");
10316     }
10317     
10318     pic16_freeAsmop(right,NULL,ic,FALSE);
10319     /* now assign DPTR to result */
10320     pic16_aopOp(result,ic,FALSE);
10321     size = AOP_SIZE(result);
10322     while (size--) {
10323         pic16_emitcode ("pop","acc");
10324         pic16_aopPut(AOP(result),"a",--offset);
10325     }
10326     pic16_freeAsmop(result,NULL,ic,FALSE);
10327         
10328 }
10329 #endif
10330
10331 /*-----------------------------------------------------------------*/
10332 /* genAssign - generate code for assignment                        */
10333 /*-----------------------------------------------------------------*/
10334 static void genAssign (iCode *ic)
10335 {
10336   operand *result, *right;
10337   int size, offset,know_W;
10338   unsigned long lit = 0L;
10339
10340   result = IC_RESULT(ic);
10341   right  = IC_RIGHT(ic) ;
10342
10343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10344   
10345   /* if they are the same */
10346   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10347     return ;
10348
10349   pic16_aopOp(right,ic,FALSE);
10350   pic16_aopOp(result,ic,TRUE);
10351
10352   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10353
10354   /* if they are the same registers */
10355   if (pic16_sameRegs(AOP(right),AOP(result)))
10356     goto release;
10357
10358   /* if the result is a bit */
10359   if (AOP_TYPE(result) == AOP_CRY) {
10360     /* if the right size is a literal then
10361        we know what the value is */
10362     if (AOP_TYPE(right) == AOP_LIT) {
10363           
10364       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10365                   pic16_popGet(AOP(result),0));
10366
10367       if (((int) operandLitValue(right))) 
10368         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10369                        AOP(result)->aopu.aop_dir,
10370                        AOP(result)->aopu.aop_dir);
10371       else
10372         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10373                        AOP(result)->aopu.aop_dir,
10374                        AOP(result)->aopu.aop_dir);
10375       goto release;
10376     }
10377
10378     /* the right is also a bit variable */
10379     if (AOP_TYPE(right) == AOP_CRY) {
10380       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10381       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10382       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10383
10384       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10385                      AOP(result)->aopu.aop_dir,
10386                      AOP(result)->aopu.aop_dir);
10387       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10388                      AOP(right)->aopu.aop_dir,
10389                      AOP(right)->aopu.aop_dir);
10390       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10391                      AOP(result)->aopu.aop_dir,
10392                      AOP(result)->aopu.aop_dir);
10393       goto release ;
10394     }
10395
10396     /* we need to or */
10397     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10398     pic16_toBoolean(right);
10399     emitSKPZ;
10400     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10401     //pic16_aopPut(AOP(result),"a",0);
10402     goto release ;
10403   }
10404
10405   /* bit variables done */
10406   /* general case */
10407   size = AOP_SIZE(result);
10408   offset = 0 ;
10409   if(AOP_TYPE(right) == AOP_LIT)
10410     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10411
10412 /* VR - What is this?! */
10413   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10414   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10415     if(aopIdx(AOP(result),0) == 4) {
10416   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10417       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10418       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10419       goto release;
10420     } else
10421       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10422   }
10423
10424   know_W=-1;
10425   while (size--) {
10426   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10427     if(AOP_TYPE(right) == AOP_LIT) {
10428       if(lit&0xff) {
10429         if(know_W != (lit&0xff))
10430           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10431         know_W = lit&0xff;
10432         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10433       } else
10434         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10435
10436       lit >>= 8;
10437
10438     } else if (AOP_TYPE(right) == AOP_CRY) {
10439       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10440       if(offset == 0) {
10441         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10442         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10443       }
10444     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10445         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10446         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10447     } else {
10448   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10449
10450 #if 1
10451         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10452            normally should work, but mind that the W register live range
10453            is not checked, so if the code generator assumes that the W
10454            is already loaded after such a pair, wrong code will be generated.
10455            
10456            Checking the live range is the next step.
10457            This is experimental code yet and has not been fully tested yet.
10458            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10459            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10460            
10461         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10462 #else   
10463         /* This is the old code, which is assumed(?!) that works fine(!?) */
10464
10465         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10466         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10467 #endif
10468     }
10469             
10470     offset++;
10471   }
10472
10473     
10474  release:
10475   pic16_freeAsmop (right,NULL,ic,FALSE);
10476   pic16_freeAsmop (result,NULL,ic,TRUE);
10477 }   
10478
10479 /*-----------------------------------------------------------------*/
10480 /* genJumpTab - generates code for jump table                       */
10481 /*-----------------------------------------------------------------*/
10482 static void genJumpTab (iCode *ic)
10483 {
10484     symbol *jtab;
10485     char *l;
10486
10487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10488
10489     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10490     /* get the condition into accumulator */
10491     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10492     MOVA(l);
10493     /* multiply by three */
10494     pic16_emitcode("add","a,acc");
10495     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10496
10497     jtab = newiTempLabel(NULL);
10498     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10499     pic16_emitcode("jmp","@a+dptr");
10500     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10501
10502     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10503     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10504     emitSKPNC;
10505     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10506     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10507     pic16_emitpLabel(jtab->key);
10508
10509     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10510
10511     /* now generate the jump labels */
10512     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10513          jtab = setNextItem(IC_JTLABELS(ic))) {
10514         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10515         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10516         
10517     }
10518
10519 }
10520
10521 /*-----------------------------------------------------------------*/
10522 /* genMixedOperation - gen code for operators between mixed types  */
10523 /*-----------------------------------------------------------------*/
10524 /*
10525   TSD - Written for the PIC port - but this unfortunately is buggy.
10526   This routine is good in that it is able to efficiently promote 
10527   types to different (larger) sizes. Unfortunately, the temporary
10528   variables that are optimized out by this routine are sometimes
10529   used in other places. So until I know how to really parse the 
10530   iCode tree, I'm going to not be using this routine :(.
10531 */
10532 static int genMixedOperation (iCode *ic)
10533 {
10534 #if 0
10535   operand *result = IC_RESULT(ic);
10536   sym_link *ctype = operandType(IC_LEFT(ic));
10537   operand *right = IC_RIGHT(ic);
10538   int ret = 0;
10539   int big,small;
10540   int offset;
10541
10542   iCode *nextic;
10543   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10544
10545   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10546
10547   nextic = ic->next;
10548   if(!nextic)
10549     return 0;
10550
10551   nextright = IC_RIGHT(nextic);
10552   nextleft  = IC_LEFT(nextic);
10553   nextresult = IC_RESULT(nextic);
10554
10555   pic16_aopOp(right,ic,FALSE);
10556   pic16_aopOp(result,ic,FALSE);
10557   pic16_aopOp(nextright,  nextic, FALSE);
10558   pic16_aopOp(nextleft,   nextic, FALSE);
10559   pic16_aopOp(nextresult, nextic, FALSE);
10560
10561   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10562
10563     operand *t = right;
10564     right = nextright;
10565     nextright = t; 
10566
10567     pic16_emitcode(";remove right +","");
10568
10569   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10570 /*
10571     operand *t = right;
10572     right = nextleft;
10573     nextleft = t; 
10574 */
10575     pic16_emitcode(";remove left +","");
10576   } else
10577     return 0;
10578
10579   big = AOP_SIZE(nextleft);
10580   small = AOP_SIZE(nextright);
10581
10582   switch(nextic->op) {
10583
10584   case '+':
10585     pic16_emitcode(";optimize a +","");
10586     /* if unsigned or not an integral type */
10587     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10588       pic16_emitcode(";add a bit to something","");
10589     } else {
10590
10591       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10592
10593       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10594         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10595         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10596       } else
10597         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10598
10599       offset = 0;
10600       while(--big) {
10601
10602         offset++;
10603
10604         if(--small) {
10605           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10606             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10607             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10608           }
10609
10610           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10611           emitSKPNC;
10612           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10613                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10614                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10615           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10616           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10617
10618         } else {
10619           pic16_emitcode("rlf","known_zero,w");
10620
10621           /*
10622             if right is signed
10623               btfsc  right,7
10624                addlw ff
10625           */
10626           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10627             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10628             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10629           } else {
10630             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10631           }
10632         }
10633       }
10634       ret = 1;
10635     }
10636   }
10637   ret = 1;
10638
10639 release:
10640   pic16_freeAsmop(right,NULL,ic,TRUE);
10641   pic16_freeAsmop(result,NULL,ic,TRUE);
10642   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10643   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10644   if(ret)
10645     nextic->generated = 1;
10646
10647   return ret;
10648 #else
10649   return 0;
10650 #endif
10651 }
10652 /*-----------------------------------------------------------------*/
10653 /* genCast - gen code for casting                                  */
10654 /*-----------------------------------------------------------------*/
10655 static void genCast (iCode *ic)
10656 {
10657   operand *result = IC_RESULT(ic);
10658   sym_link *ctype = operandType(IC_LEFT(ic));
10659   sym_link *rtype = operandType(IC_RIGHT(ic));
10660   operand *right = IC_RIGHT(ic);
10661   int size, offset ;
10662
10663         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10664         /* if they are equivalent then do nothing */
10665         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10666                 return ;
10667
10668         pic16_aopOp(right,ic,FALSE) ;
10669         pic16_aopOp(result,ic,FALSE);
10670
10671         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10672
10673         /* if the result is a bit */
10674         if (AOP_TYPE(result) == AOP_CRY) {
10675         
10676                 /* if the right size is a literal then
10677                  * we know what the value is */
10678                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10679
10680                 if (AOP_TYPE(right) == AOP_LIT) {
10681                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10682                                 pic16_popGet(AOP(result),0));
10683
10684                         if (((int) operandLitValue(right))) 
10685                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10686                                         AOP(result)->aopu.aop_dir,
10687                                         AOP(result)->aopu.aop_dir);
10688                         else
10689                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10690                                         AOP(result)->aopu.aop_dir,
10691                                         AOP(result)->aopu.aop_dir);
10692                         goto release;
10693                 }
10694
10695                 /* the right is also a bit variable */
10696                 if (AOP_TYPE(right) == AOP_CRY) {
10697                         emitCLRC;
10698                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10699
10700                         pic16_emitcode("clrc","");
10701                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10702                                 AOP(right)->aopu.aop_dir,
10703                                 AOP(right)->aopu.aop_dir);
10704                         pic16_aopPut(AOP(result),"c",0);
10705                         goto release ;
10706                 }
10707
10708                 /* we need to or */
10709                 if (AOP_TYPE(right) == AOP_REG) {
10710                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10711                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10712                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10713                 }
10714                 pic16_toBoolean(right);
10715                 pic16_aopPut(AOP(result),"a",0);
10716                 goto release ;
10717         }
10718
10719         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10720           int offset = 1;
10721
10722                 size = AOP_SIZE(result);
10723
10724                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10725
10726                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10727                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10728                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10729
10730                 while (size--)
10731                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10732
10733                 goto release;
10734         }
10735
10736         /* if they are the same size : or less */
10737         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10738
10739                 /* if they are in the same place */
10740                 if (pic16_sameRegs(AOP(right),AOP(result)))
10741                         goto release;
10742
10743                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10744 #if 0
10745                 if (IS_PTR_CONST(rtype))
10746 #else
10747                 if (IS_CODEPTR(rtype))
10748 #endif
10749                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10750
10751 #if 0
10752                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10753 #else
10754                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10755 #endif
10756                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10757
10758 #if 0
10759                 if(AOP_TYPE(right) == AOP_IMMD) {
10760                   pCodeOp *pcop0, *pcop1, *pcop2;
10761                   symbol *sym = OP_SYMBOL( right );
10762
10763                         size = AOP_SIZE(result);
10764                         /* low */
10765                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10766                         /* high */
10767                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10768                         /* upper */
10769                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10770         
10771                         if (size == 3) {
10772                                 pic16_emitpcode(POC_MOVLW, pcop0);
10773                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10774                                 pic16_emitpcode(POC_MOVLW, pcop1);
10775                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10776                                 pic16_emitpcode(POC_MOVLW, pcop2);
10777                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10778                         } else
10779                         if (size == 2) {
10780                                 pic16_emitpcode(POC_MOVLW, pcop0);
10781                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10782                                 pic16_emitpcode(POC_MOVLW, pcop1);
10783                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10784                         } else {
10785                                 pic16_emitpcode(POC_MOVLW, pcop0);
10786                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10787                         }
10788                 } else
10789 #endif
10790                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10791                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10792                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10793                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10794                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10795                         if(AOP_SIZE(result) <2)
10796                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10797                 } else {
10798                         /* if they in different places then copy */
10799                         size = AOP_SIZE(result);
10800                         offset = 0 ;
10801                         while (size--) {
10802                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10803                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10804                                 offset++;
10805                         }
10806                 }
10807                 goto release;
10808         }
10809
10810         /* if the result is of type pointer */
10811         if (IS_PTR(ctype)) {
10812           int p_type;
10813           sym_link *type = operandType(right);
10814           sym_link *etype = getSpec(type);
10815
10816                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10817
10818                 /* pointer to generic pointer */
10819                 if (IS_GENPTR(ctype)) {
10820                   char *l = zero;
10821             
10822                         if (IS_PTR(type)) 
10823                                 p_type = DCL_TYPE(type);
10824                         else {
10825                 /* we have to go by the storage class */
10826                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10827
10828 /*              if (SPEC_OCLS(etype)->codesp )  */
10829 /*                  p_type = CPOINTER ;  */
10830 /*              else */
10831 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10832 /*                      p_type = FPOINTER ; */
10833 /*                  else */
10834 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10835 /*                          p_type = PPOINTER; */
10836 /*                      else */
10837 /*                          if (SPEC_OCLS(etype) == idata ) */
10838 /*                              p_type = IPOINTER ; */
10839 /*                          else */
10840 /*                              p_type = POINTER ; */
10841             }
10842                 
10843             /* the first two bytes are known */
10844       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10845             size = GPTRSIZE - 1; 
10846             offset = 0 ;
10847             while (size--) {
10848               if(offset < AOP_SIZE(right)) {
10849       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10850                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10851                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10852                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10853                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10854                 } else { 
10855                   pic16_aopPut(AOP(result),
10856                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10857                          offset);
10858                 }
10859               } else 
10860                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10861               offset++;
10862             }
10863             /* the last byte depending on type */
10864             switch (p_type) {
10865             case IPOINTER:
10866             case POINTER:
10867                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10868                 break;
10869             case FPOINTER:
10870               pic16_emitcode(";BUG!? ","%d",__LINE__);
10871                 l = one;
10872                 break;
10873             case CPOINTER:
10874               pic16_emitcode(";BUG!? ","%d",__LINE__);
10875                 l = "#0x02";
10876                 break;                          
10877             case PPOINTER:
10878               pic16_emitcode(";BUG!? ","%d",__LINE__);
10879                 l = "#0x03";
10880                 break;
10881                 
10882             default:
10883                 /* this should never happen */
10884                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10885                        "got unknown pointer type");
10886                 exit(1);
10887             }
10888             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10889             goto release ;
10890         }
10891         
10892         /* just copy the pointers */
10893         size = AOP_SIZE(result);
10894         offset = 0 ;
10895         while (size--) {
10896             pic16_aopPut(AOP(result),
10897                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10898                    offset);
10899             offset++;
10900         }
10901         goto release ;
10902     }
10903     
10904
10905
10906     /* so we now know that the size of destination is greater
10907     than the size of the source.
10908     Now, if the next iCode is an operator then we might be
10909     able to optimize the operation without performing a cast.
10910     */
10911     if(genMixedOperation(ic))
10912       goto release;
10913
10914     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10915     
10916     /* we move to result for the size of source */
10917     size = AOP_SIZE(right);
10918     offset = 0 ;
10919     while (size--) {
10920       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10921       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10922       offset++;
10923     }
10924
10925     /* now depending on the sign of the destination */
10926     size = AOP_SIZE(result) - AOP_SIZE(right);
10927     /* if unsigned or not an integral type */
10928     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
10929       while (size--)
10930         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10931     } else {
10932       /* we need to extend the sign :( */
10933
10934       if(size == 1) {
10935         /* Save one instruction of casting char to int */
10936         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10937         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10938         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10939       } else {
10940         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10941
10942         if(offset)
10943           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10944         else
10945           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10946         
10947         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10948
10949         while (size--)
10950           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10951       }
10952     }
10953
10954 release:
10955     pic16_freeAsmop(right,NULL,ic,TRUE);
10956     pic16_freeAsmop(result,NULL,ic,TRUE);
10957
10958 }
10959
10960 /*-----------------------------------------------------------------*/
10961 /* genDjnz - generate decrement & jump if not zero instrucion      */
10962 /*-----------------------------------------------------------------*/
10963 static int genDjnz (iCode *ic, iCode *ifx)
10964 {
10965     symbol *lbl, *lbl1;
10966     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10967
10968     if (!ifx)
10969         return 0;
10970     
10971     /* if the if condition has a false label
10972        then we cannot save */
10973     if (IC_FALSE(ifx))
10974         return 0;
10975
10976     /* if the minus is not of the form 
10977        a = a - 1 */
10978     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10979         !IS_OP_LITERAL(IC_RIGHT(ic)))
10980         return 0;
10981
10982     if (operandLitValue(IC_RIGHT(ic)) != 1)
10983         return 0;
10984
10985     /* if the size of this greater than one then no
10986        saving */
10987     if (getSize(operandType(IC_RESULT(ic))) > 1)
10988         return 0;
10989
10990     /* otherwise we can save BIG */
10991     lbl = newiTempLabel(NULL);
10992     lbl1= newiTempLabel(NULL);
10993
10994     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10995     
10996     if (IS_AOP_PREG(IC_RESULT(ic))) {
10997         pic16_emitcode("dec","%s",
10998                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10999         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11000         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11001     } else {    
11002
11003
11004       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11005       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11006
11007       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11008       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11009
11010     }
11011 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11012 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11013 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11014 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11015
11016     
11017     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11018     ifx->generated = 1;
11019     return 1;
11020 }
11021
11022 /*-----------------------------------------------------------------*/
11023 /* genReceive - generate code for a receive iCode                  */
11024 /*-----------------------------------------------------------------*/
11025 static void genReceive (iCode *ic)
11026 {    
11027         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11028
11029         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11030                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11031                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11032
11033           int size = getSize(operandType(IC_RESULT(ic)));
11034           int offset =  pic16_fReturnSizePic - size;
11035
11036                 while (size--) {
11037                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11038                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11039                         offset++;
11040                 }
11041
11042                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11043
11044                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11045                 size = AOP_SIZE(IC_RESULT(ic));
11046                 offset = 0;
11047                 while (size--) {
11048                         pic16_emitcode ("pop","acc");
11049                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11050                 }
11051         } else {
11052                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11053
11054                 _G.accInUse++;
11055                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11056                 _G.accInUse--;
11057                 assignResultValue(IC_RESULT(ic), 0);
11058         }
11059
11060         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11061 }
11062
11063 /*-----------------------------------------------------------------*/
11064 /* genDummyRead - generate code for dummy read of volatiles        */
11065 /*-----------------------------------------------------------------*/
11066 static void
11067 genDummyRead (iCode * ic)
11068 {
11069   pic16_emitcode ("; genDummyRead","");
11070   pic16_emitcode ("; not implemented","");
11071
11072   ic = ic;
11073 }
11074
11075 /*-----------------------------------------------------------------*/
11076 /* genpic16Code - generate code for pic16 based controllers        */
11077 /*-----------------------------------------------------------------*/
11078 /*
11079  * At this point, ralloc.c has gone through the iCode and attempted
11080  * to optimize in a way suitable for a PIC. Now we've got to generate
11081  * PIC instructions that correspond to the iCode.
11082  *
11083  * Once the instructions are generated, we'll pass through both the
11084  * peep hole optimizer and the pCode optimizer.
11085  *-----------------------------------------------------------------*/
11086
11087 void genpic16Code (iCode *lic)
11088 {
11089     iCode *ic;
11090     int cln = 0;
11091
11092     lineHead = lineCurr = NULL;
11093
11094     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11095     pic16_addpBlock(pb);
11096
11097 #if 0
11098     /* if debug information required */
11099     if (options.debug && currFunc) {
11100       if (currFunc) {
11101         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11102         _G.debugLine = 1;
11103         if (IS_STATIC(currFunc->etype)) {
11104           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
11105           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
11106         } else {
11107           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
11108           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
11109         }
11110         _G.debugLine = 0;
11111       }
11112     }
11113 #endif
11114
11115     for (ic = lic ; ic ; ic = ic->next ) {
11116
11117       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11118         if ( cln != ic->lineno ) {
11119             if ( options.debug ) {
11120                 _G.debugLine = 1;
11121                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
11122                          FileBaseName(ic->filename),ic->lineno,
11123                          ic->level,ic->block);
11124                 _G.debugLine = 0;
11125             }
11126             
11127             if(!options.noCcodeInAsm) {
11128                 pic16_addpCode2pBlock(pb,
11129                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11130                                 printCLine(ic->filename, ic->lineno)));
11131             }
11132
11133             cln = ic->lineno ;
11134         }
11135         
11136         if(options.iCodeInAsm) {
11137                 /* insert here code to print iCode as comment */
11138                 pic16_emitpcomment("ic:%d: %s", ic->seq, printILine(ic));
11139         }
11140         
11141         /* if the result is marked as
11142            spilt and rematerializable or code for
11143            this has already been generated then
11144            do nothing */
11145         if (resultRemat(ic) || ic->generated ) 
11146             continue ;
11147         
11148         /* depending on the operation */
11149         switch (ic->op) {
11150         case '!' :
11151             pic16_genNot(ic);
11152             break;
11153             
11154         case '~' :
11155             pic16_genCpl(ic);
11156             break;
11157             
11158         case UNARYMINUS:
11159             genUminus (ic);
11160             break;
11161             
11162         case IPUSH:
11163             genIpush (ic);
11164             break;
11165             
11166         case IPOP:
11167             /* IPOP happens only when trying to restore a 
11168                spilt live range, if there is an ifx statement
11169                following this pop then the if statement might
11170                be using some of the registers being popped which
11171                would destroy the contents of the register so
11172                we need to check for this condition and handle it */
11173             if (ic->next            && 
11174                 ic->next->op == IFX &&
11175                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11176                 genIfx (ic->next,ic);
11177             else
11178                 genIpop (ic);
11179             break; 
11180             
11181         case CALL:
11182             genCall (ic);
11183             break;
11184             
11185         case PCALL:
11186             genPcall (ic);
11187             break;
11188             
11189         case FUNCTION:
11190             genFunction (ic);
11191             break;
11192             
11193         case ENDFUNCTION:
11194             genEndFunction (ic);
11195             break;
11196             
11197         case RETURN:
11198             genRet (ic);
11199             break;
11200             
11201         case LABEL:
11202             genLabel (ic);
11203             break;
11204             
11205         case GOTO:
11206             genGoto (ic);
11207             break;
11208             
11209         case '+' :
11210             pic16_genPlus (ic) ;
11211             break;
11212             
11213         case '-' :
11214             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11215                 pic16_genMinus (ic);
11216             break;
11217             
11218         case '*' :
11219             genMult (ic);
11220             break;
11221             
11222         case '/' :
11223             genDiv (ic) ;
11224             break;
11225             
11226         case '%' :
11227             genMod (ic);
11228             break;
11229             
11230         case '>' :
11231             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11232             break;
11233             
11234         case '<' :
11235             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11236             break;
11237             
11238         case LE_OP:
11239         case GE_OP:
11240         case NE_OP:
11241             
11242             /* note these two are xlated by algebraic equivalence
11243                during parsing SDCC.y */
11244             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11245                    "got '>=' or '<=' shouldn't have come here");
11246             break;      
11247             
11248         case EQ_OP:
11249             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11250             break;          
11251             
11252         case AND_OP:
11253             genAndOp (ic);
11254             break;
11255             
11256         case OR_OP:
11257             genOrOp (ic);
11258             break;
11259             
11260         case '^' :
11261             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11262             break;
11263             
11264         case '|' :
11265                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11266             break;
11267             
11268         case BITWISEAND:
11269             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11270             break;
11271             
11272         case INLINEASM:
11273             genInline (ic);
11274             break;
11275             
11276         case RRC:
11277             genRRC (ic);
11278             break;
11279             
11280         case RLC:
11281             genRLC (ic);
11282             break;
11283             
11284         case GETHBIT:
11285             genGetHbit (ic);
11286             break;
11287             
11288         case LEFT_OP:
11289             genLeftShift (ic);
11290             break;
11291             
11292         case RIGHT_OP:
11293             genRightShift (ic);
11294             break;
11295             
11296         case GET_VALUE_AT_ADDRESS:
11297             genPointerGet(ic);
11298             break;
11299             
11300         case '=' :
11301             if (POINTER_SET(ic))
11302                 genPointerSet(ic);
11303             else
11304                 genAssign(ic);
11305             break;
11306             
11307         case IFX:
11308             genIfx (ic,NULL);
11309             break;
11310             
11311         case ADDRESS_OF:
11312             genAddrOf (ic);
11313             break;
11314             
11315         case JUMPTABLE:
11316             genJumpTab (ic);
11317             break;
11318             
11319         case CAST:
11320             genCast (ic);
11321             break;
11322             
11323         case RECEIVE:
11324             genReceive(ic);
11325             break;
11326             
11327         case SEND:
11328             addSet(&_G.sendSet,ic);
11329             break;
11330
11331         case DUMMY_READ_VOLATILE:
11332           genDummyRead (ic);
11333           break;
11334
11335         default :
11336             ic = ic;
11337         }
11338     }
11339
11340
11341     /* now we are ready to call the
11342        peep hole optimizer */
11343     if (!options.nopeep) {
11344       peepHole (&lineHead);
11345     }
11346     /* now do the actual printing */
11347     printLine (lineHead,codeOutFile);
11348
11349 #ifdef PCODE_DEBUG
11350     DFPRINTF((stderr,"printing pBlock\n\n"));
11351     pic16_printpBlock(stdout,pb);
11352 #endif
11353
11354     return;
11355 }
11356