dc423a941370b34efdff32b49b27f10dcde90d2b
[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 #if 0
4336 // not needed ATM
4337
4338 /*-----------------------------------------------------------------*/
4339 /* genSkip                                                         */
4340 /*-----------------------------------------------------------------*/
4341 static void genSkip(iCode *ifx,int status_bit)
4342 {
4343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4344   if(!ifx)
4345     return;
4346
4347   if ( IC_TRUE(ifx) ) {
4348     switch(status_bit) {
4349     case 'z':
4350       emitSKPNZ;
4351       break;
4352
4353     case 'c':
4354       emitSKPNC;
4355       break;
4356
4357     case 'd':
4358       emitSKPDC;
4359       break;
4360
4361     }
4362
4363     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4364     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4365
4366   } else {
4367
4368     switch(status_bit) {
4369
4370     case 'z':
4371       emitSKPZ;
4372       break;
4373
4374     case 'c':
4375       emitSKPC;
4376       break;
4377
4378     case 'd':
4379       emitSKPDC;
4380       break;
4381     }
4382     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4383     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4384
4385   }
4386
4387 }
4388 #endif
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genSkipc                                                        */
4392 /*-----------------------------------------------------------------*/
4393 static void genSkipc(resolvedIfx *rifx)
4394 {
4395   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4396   
4397   if(!rifx)
4398     return;
4399
4400   if(rifx->condition)
4401     emitSKPC;
4402   else
4403     emitSKPNC;
4404
4405   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4406   rifx->generated = 1;
4407 }
4408
4409 /*-----------------------------------------------------------------*/
4410 /* genSkipz2                                                       */
4411 /*-----------------------------------------------------------------*/
4412 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4413 {
4414   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4415   
4416   if(!rifx)
4417     return;
4418
4419   if( (rifx->condition ^ invert_condition) & 1)
4420     emitSKPZ;
4421   else
4422     emitSKPNZ;
4423
4424   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4425   rifx->generated = 1;
4426 }
4427
4428 #if 0
4429 /*-----------------------------------------------------------------*/
4430 /* genSkipz                                                        */
4431 /*-----------------------------------------------------------------*/
4432 static void genSkipz(iCode *ifx, int condition)
4433 {
4434   if(!ifx)
4435     return;
4436
4437   if(condition)
4438     emitSKPNZ;
4439   else
4440     emitSKPZ;
4441
4442   if ( IC_TRUE(ifx) )
4443     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4444   else
4445     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4446
4447   if ( IC_TRUE(ifx) )
4448     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4449   else
4450     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4451
4452 }
4453 #endif
4454
4455 /*-----------------------------------------------------------------*/
4456 /* genSkipCond                                                     */
4457 /*-----------------------------------------------------------------*/
4458 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4459 {
4460   if(!rifx)
4461     return;
4462
4463   if(rifx->condition)
4464     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4465   else
4466     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4467
4468
4469   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4470   rifx->generated = 1;
4471 }
4472
4473 #if 0
4474 /*-----------------------------------------------------------------*/
4475 /* genChkZeroes :- greater or less than comparison                 */
4476 /*     For each byte in a literal that is zero, inclusive or the   */
4477 /*     the corresponding byte in the operand with W                */
4478 /*     returns true if any of the bytes are zero                   */
4479 /*-----------------------------------------------------------------*/
4480 static int genChkZeroes(operand *op, int lit,  int size)
4481 {
4482
4483   int i;
4484   int flag =1;
4485
4486   while(size--) {
4487     i = (lit >> (size*8)) & 0xff;
4488
4489     if(i==0) {
4490       if(flag) 
4491         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4492       else
4493         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4494       flag = 0;
4495     }
4496   }
4497
4498   return (flag==0);
4499 }
4500 #endif
4501
4502 /*-----------------------------------------------------------------*/
4503 /* genCmp :- greater or less than comparison                       */
4504 /*-----------------------------------------------------------------*/
4505 static void genCmp (operand *left,operand *right,
4506                     operand *result, iCode *ifx, int sign)
4507 {
4508   int size; //, offset = 0 ;
4509   unsigned long lit = 0L,i = 0;
4510   resolvedIfx rFalseIfx;
4511   //  resolvedIfx rTrueIfx;
4512   symbol *truelbl;
4513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4514 /*
4515   if(ifx) {
4516     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4517     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4518   }
4519 */
4520
4521   resolveIfx(&rFalseIfx,ifx);
4522   truelbl  = newiTempLabel(NULL);
4523   size = max(AOP_SIZE(left),AOP_SIZE(right));
4524
4525   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4526
4527 #define _swapp
4528
4529   /* if literal is on the right then swap with left */
4530   if ((AOP_TYPE(right) == AOP_LIT)) {
4531     operand *tmp = right ;
4532     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4533     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4534 #ifdef _swapp
4535
4536     lit = (lit - 1) & mask;
4537     right = left;
4538     left = tmp;
4539     rFalseIfx.condition ^= 1;
4540 #endif
4541
4542   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4543     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4544   }
4545
4546
4547   //if(IC_TRUE(ifx) == NULL)
4548   /* if left & right are bit variables */
4549   if (AOP_TYPE(left) == AOP_CRY &&
4550       AOP_TYPE(right) == AOP_CRY ) {
4551     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4552     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4553   } else {
4554     /* subtract right from left if at the
4555        end the carry flag is set then we know that
4556        left is greater than right */
4557
4558     symbol *lbl  = newiTempLabel(NULL);
4559
4560 #if 0
4561         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4562                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4563 #endif
4564
4565 #ifndef _swapp
4566     if(AOP_TYPE(right) == AOP_LIT) {
4567
4568       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4569
4570       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4571
4572       /* special cases */
4573
4574       if(lit == 0) {
4575
4576         if(sign != 0) 
4577           genSkipCond(&rFalseIfx,left,size-1,7);
4578         else 
4579           /* no need to compare to 0...*/
4580           /* NOTE: this is a de-generate compare that most certainly 
4581            *       creates some dead code. */
4582           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4583
4584         if(ifx) ifx->generated = 1;
4585         return;
4586
4587       }
4588       size--;
4589
4590       if(size == 0) {
4591         //i = (lit >> (size*8)) & 0xff;
4592         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4593         
4594         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4595
4596         i = ((0-lit) & 0xff);
4597         if(sign) {
4598           if( i == 0x81) { 
4599             /* lit is 0x7f, all signed chars are less than
4600              * this except for 0x7f itself */
4601             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4602             genSkipz2(&rFalseIfx,0);
4603           } else {
4604             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4605             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4606             genSkipc(&rFalseIfx);
4607           }
4608
4609         } else {
4610           if(lit == 1) {
4611             genSkipz2(&rFalseIfx,1);
4612           } else {
4613             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4614             genSkipc(&rFalseIfx);
4615           }
4616         }
4617
4618         if(ifx) ifx->generated = 1;
4619         return;
4620       }
4621
4622       /* chars are out of the way. now do ints and longs */
4623
4624
4625       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4626         
4627       /* special cases */
4628
4629       if(sign) {
4630
4631         if(lit == 0) {
4632           genSkipCond(&rFalseIfx,left,size,7);
4633           if(ifx) ifx->generated = 1;
4634           return;
4635         }
4636
4637         if(lit <0x100) {
4638           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4639
4640           //rFalseIfx.condition ^= 1;
4641           //genSkipCond(&rFalseIfx,left,size,7);
4642           //rFalseIfx.condition ^= 1;
4643
4644           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4645           if(rFalseIfx.condition)
4646             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4647           else
4648             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4649
4650           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4651           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4652           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4653
4654           while(size > 1)
4655             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4656
4657           if(rFalseIfx.condition) {
4658             emitSKPZ;
4659             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4660
4661           } else {
4662             emitSKPNZ;
4663           }
4664
4665           genSkipc(&rFalseIfx);
4666           pic16_emitpLabel(truelbl->key);
4667           if(ifx) ifx->generated = 1;
4668           return;
4669
4670         }
4671
4672         if(size == 1) {
4673
4674           if( (lit & 0xff) == 0) {
4675             /* lower byte is zero */
4676             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4677             i = ((lit >> 8) & 0xff) ^0x80;
4678             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4679             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4680             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4681             genSkipc(&rFalseIfx);
4682
4683
4684             if(ifx) ifx->generated = 1;
4685             return;
4686
4687           }
4688         } else {
4689           /* Special cases for signed longs */
4690           if( (lit & 0xffffff) == 0) {
4691             /* lower byte is zero */
4692             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4693             i = ((lit >> 8*3) & 0xff) ^0x80;
4694             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4695             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4696             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4697             genSkipc(&rFalseIfx);
4698
4699
4700             if(ifx) ifx->generated = 1;
4701             return;
4702
4703           }
4704
4705         }
4706
4707
4708         if(lit & (0x80 << (size*8))) {
4709           /* lit is negative */
4710           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4711
4712           //genSkipCond(&rFalseIfx,left,size,7);
4713
4714           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4715
4716           if(rFalseIfx.condition)
4717             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4718           else
4719             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4720
4721
4722         } else {
4723           /* lit is positive */
4724           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4725           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4726           if(rFalseIfx.condition)
4727             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4728           else
4729             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4730
4731         }
4732
4733         /*
4734           This works, but is only good for ints.
4735           It also requires a "known zero" register.
4736           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4737           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4738           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4739           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4740           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4741           genSkipc(&rFalseIfx);
4742
4743           pic16_emitpLabel(truelbl->key);
4744           if(ifx) ifx->generated = 1;
4745           return;
4746         **/
4747           
4748         /* There are no more special cases, so perform a general compare */
4749   
4750         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4751         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4752
4753         while(size--) {
4754
4755           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4756           emitSKPNZ;
4757           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4758         }
4759         //rFalseIfx.condition ^= 1;
4760         genSkipc(&rFalseIfx);
4761
4762         pic16_emitpLabel(truelbl->key);
4763
4764         if(ifx) ifx->generated = 1;
4765         return;
4766
4767
4768       }
4769
4770
4771       /* sign is out of the way. So now do an unsigned compare */
4772       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4773
4774
4775       /* General case - compare to an unsigned literal on the right.*/
4776
4777       i = (lit >> (size*8)) & 0xff;
4778       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4779       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4780       while(size--) {
4781         i = (lit >> (size*8)) & 0xff;
4782
4783         if(i) {
4784           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4785           emitSKPNZ;
4786           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4787         } else {
4788           /* this byte of the lit is zero, 
4789            *if it's not the last then OR in the variable */
4790           if(size)
4791             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4792         }
4793       }
4794
4795
4796       pic16_emitpLabel(lbl->key);
4797 //      pic16_emitpLabel(truelbl->key);
4798       //if(emitFinalCheck)
4799       genSkipc(&rFalseIfx);
4800       if(sign)
4801         pic16_emitpLabel(truelbl->key);
4802
4803       if(ifx) ifx->generated = 1;
4804       return;
4805
4806
4807     }
4808 #endif  // _swapp
4809
4810     if(AOP_TYPE(left) == AOP_LIT) {
4811       //symbol *lbl = newiTempLabel(NULL);
4812
4813       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4814
4815
4816       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4817
4818       /* Special cases */
4819       if((lit == 0) && (sign == 0)){
4820
4821         size--;
4822         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4823         while(size) 
4824           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4825
4826         genSkipz2(&rFalseIfx,0);
4827         if(ifx) ifx->generated = 1;
4828         return;
4829       }
4830
4831       if(size==1) {
4832         /* Special cases */
4833         lit &= 0xff;
4834         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4835           /* degenerate compare can never be true */
4836           if(rFalseIfx.condition == 0)
4837             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4838
4839           if(ifx) ifx->generated = 1;
4840           return;
4841         }
4842
4843         if(sign) {
4844           /* signed comparisons to a literal byte */
4845
4846           int lp1 = (lit+1) & 0xff;
4847
4848           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4849           switch (lp1) {
4850           case 0:
4851             rFalseIfx.condition ^= 1;
4852             genSkipCond(&rFalseIfx,right,0,7);
4853             break;
4854           case 0x7f:
4855             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4856             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4857             genSkipz2(&rFalseIfx,1);
4858             break;
4859           default:
4860             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4861             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4862             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4863             rFalseIfx.condition ^= 1;
4864             genSkipc(&rFalseIfx);
4865             break;
4866           }
4867         } else {
4868           /* unsigned comparisons to a literal byte */
4869
4870           switch(lit & 0xff ) {
4871           case 0:
4872             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4873             genSkipz2(&rFalseIfx,0);
4874             break;
4875           case 0x7f:
4876             rFalseIfx.condition ^= 1;
4877             genSkipCond(&rFalseIfx,right,0,7);
4878             break;
4879
4880           default:
4881             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4882             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4883             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4884             rFalseIfx.condition ^= 1;
4885             if (AOP_TYPE(result) == AOP_CRY)
4886               genSkipc(&rFalseIfx);
4887             else {
4888               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4889               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4890             }         
4891             break;
4892           }
4893         }
4894
4895         if(ifx) ifx->generated = 1;
4896         //goto check_carry;
4897         return;
4898
4899       } else {
4900
4901         /* Size is greater than 1 */
4902
4903         if(sign) {
4904           int lp1 = lit+1;
4905
4906           size--;
4907
4908           if(lp1 == 0) {
4909             /* this means lit = 0xffffffff, or -1 */
4910
4911
4912             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4913             rFalseIfx.condition ^= 1;
4914             genSkipCond(&rFalseIfx,right,size,7);
4915             if(ifx) ifx->generated = 1;
4916             return;
4917           }
4918
4919           if(lit == 0) {
4920             int s = size;
4921
4922             if(rFalseIfx.condition) {
4923               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4924               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4925             }
4926
4927             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4928             while(size--)
4929               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4930
4931
4932             emitSKPZ;
4933             if(rFalseIfx.condition) {
4934               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4935               pic16_emitpLabel(truelbl->key);
4936             }else {
4937               rFalseIfx.condition ^= 1;
4938               genSkipCond(&rFalseIfx,right,s,7);
4939             }
4940
4941             if(ifx) ifx->generated = 1;
4942             return;
4943           }
4944
4945           if((size == 1) &&  (0 == (lp1&0xff))) {
4946             /* lower byte of signed word is zero */
4947             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4948             i = ((lp1 >> 8) & 0xff) ^0x80;
4949             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4950             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4951             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4952             rFalseIfx.condition ^= 1;
4953             genSkipc(&rFalseIfx);
4954
4955
4956             if(ifx) ifx->generated = 1;
4957             return;
4958           }
4959
4960           if(lit & (0x80 << (size*8))) {
4961             /* Lit is less than zero */
4962             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4963             //rFalseIfx.condition ^= 1;
4964             //genSkipCond(&rFalseIfx,left,size,7);
4965             //rFalseIfx.condition ^= 1;
4966             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4967             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4968
4969             if(rFalseIfx.condition)
4970               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4971             else
4972               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4973
4974
4975           } else {
4976             /* Lit is greater than or equal to zero */
4977             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4978             //rFalseIfx.condition ^= 1;
4979             //genSkipCond(&rFalseIfx,right,size,7);
4980             //rFalseIfx.condition ^= 1;
4981
4982             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4983             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4984
4985             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4986             if(rFalseIfx.condition)
4987               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4988             else
4989               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4990
4991           }
4992
4993
4994           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4995           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4996
4997           while(size--) {
4998
4999             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5000             emitSKPNZ;
5001             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5002           }
5003           rFalseIfx.condition ^= 1;
5004           //rFalseIfx.condition = 1;
5005           genSkipc(&rFalseIfx);
5006
5007           pic16_emitpLabel(truelbl->key);
5008
5009           if(ifx) ifx->generated = 1;
5010           return;
5011           // end of if (sign)
5012         } else {
5013
5014           /* compare word or long to an unsigned literal on the right.*/
5015
5016
5017           size--;
5018           if(lit < 0xff) {
5019             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5020             switch (lit) {
5021             case 0:
5022               break; /* handled above */
5023 /*
5024             case 0xff:
5025               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5026               while(size--)
5027                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5028               genSkipz2(&rFalseIfx,0);
5029               break;
5030 */
5031             default:
5032               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5033               while(--size)
5034                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5035
5036               emitSKPZ;
5037               if(rFalseIfx.condition)
5038                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5039               else
5040                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5041
5042
5043               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5044               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5045
5046               rFalseIfx.condition ^= 1;
5047               genSkipc(&rFalseIfx);
5048             }
5049
5050             pic16_emitpLabel(truelbl->key);
5051
5052             if(ifx) ifx->generated = 1;
5053             return;
5054           }
5055
5056
5057           lit++;
5058           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5059           i = (lit >> (size*8)) & 0xff;
5060
5061           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5062           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5063
5064           while(size--) {
5065             i = (lit >> (size*8)) & 0xff;
5066
5067             if(i) {
5068               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5069               emitSKPNZ;
5070               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5071             } else {
5072               /* this byte of the lit is zero, 
5073                * if it's not the last then OR in the variable */
5074               if(size)
5075                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5076             }
5077           }
5078
5079
5080           pic16_emitpLabel(lbl->key);
5081
5082           rFalseIfx.condition ^= 1;
5083
5084           genSkipc(&rFalseIfx);
5085         }
5086
5087         if(sign)
5088           pic16_emitpLabel(truelbl->key);
5089         if(ifx) ifx->generated = 1;
5090         return;
5091       }
5092     }
5093     /* Compare two variables */
5094
5095     DEBUGpic16_emitcode(";sign","%d",sign);
5096
5097     size--;
5098     if(sign) {
5099       /* Sigh. thus sucks... */
5100       if(size) {
5101         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5102         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5103         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5104         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5105         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5106         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5107       } else {
5108         /* Signed char comparison */
5109         /* Special thanks to Nikolai Golovchenko for this snippet */
5110         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5111         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5112         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5113         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5114         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5115         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5116
5117         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5118         genSkipc(&rFalseIfx);
5119           
5120         if(ifx) ifx->generated = 1;
5121         return;
5122       }
5123
5124     } else {
5125
5126       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5127       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5128     }
5129
5130
5131     /* The rest of the bytes of a multi-byte compare */
5132     while (size) {
5133
5134       emitSKPZ;
5135       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5136       size--;
5137
5138       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5139       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5140
5141
5142     }
5143
5144     pic16_emitpLabel(lbl->key);
5145
5146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5147     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5148         (AOP_TYPE(result) == AOP_REG)) {
5149       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5150       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5151     } else {
5152       genSkipc(&rFalseIfx);
5153     }         
5154     //genSkipc(&rFalseIfx);
5155     if(ifx) ifx->generated = 1;
5156
5157     return;
5158
5159   }
5160
5161   // check_carry:
5162   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5164     pic16_outBitC(result);
5165   } else {
5166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5167     /* if the result is used in the next
5168        ifx conditional branch then generate
5169        code a little differently */
5170     if (ifx )
5171       genIfxJump (ifx,"c");
5172     else
5173       pic16_outBitC(result);
5174     /* leave the result in acc */
5175   }
5176
5177 }
5178
5179 /*-----------------------------------------------------------------*/
5180 /* genCmpGt :- greater than comparison                             */
5181 /*-----------------------------------------------------------------*/
5182 static void genCmpGt (iCode *ic, iCode *ifx)
5183 {
5184     operand *left, *right, *result;
5185     sym_link *letype , *retype;
5186     int sign ;
5187
5188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5189     left = IC_LEFT(ic);
5190     right= IC_RIGHT(ic);
5191     result = IC_RESULT(ic);
5192
5193     letype = getSpec(operandType(left));
5194     retype =getSpec(operandType(right));
5195     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5196     /* assign the amsops */
5197     pic16_aopOp (left,ic,FALSE);
5198     pic16_aopOp (right,ic,FALSE);
5199     pic16_aopOp (result,ic,TRUE);
5200
5201     genCmp(right, left, result, ifx, sign);
5202
5203     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5204     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5205     pic16_freeAsmop(result,NULL,ic,TRUE); 
5206 }
5207
5208 /*-----------------------------------------------------------------*/
5209 /* genCmpLt - less than comparisons                                */
5210 /*-----------------------------------------------------------------*/
5211 static void genCmpLt (iCode *ic, iCode *ifx)
5212 {
5213     operand *left, *right, *result;
5214     sym_link *letype , *retype;
5215     int sign ;
5216
5217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5218     left = IC_LEFT(ic);
5219     right= IC_RIGHT(ic);
5220     result = IC_RESULT(ic);
5221
5222     letype = getSpec(operandType(left));
5223     retype =getSpec(operandType(right));
5224     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5225
5226     /* assign the amsops */
5227     pic16_aopOp (left,ic,FALSE);
5228     pic16_aopOp (right,ic,FALSE);
5229     pic16_aopOp (result,ic,TRUE);
5230
5231     genCmp(left, right, result, ifx, sign);
5232
5233     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5234     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5235     pic16_freeAsmop(result,NULL,ic,TRUE); 
5236 }
5237
5238 #if 0
5239 // not needed ATM
5240 // FIXME reenable literal optimisation when the pic16 port is stable
5241
5242 /*-----------------------------------------------------------------*/
5243 /* genc16bit2lit - compare a 16 bit value to a literal             */
5244 /*-----------------------------------------------------------------*/
5245 static void genc16bit2lit(operand *op, int lit, int offset)
5246 {
5247   int i;
5248
5249   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5250   if( (lit&0xff) == 0) 
5251     i=1;
5252   else
5253     i=0;
5254
5255   switch( BYTEofLONG(lit,i)) { 
5256   case 0:
5257     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5258     break;
5259   case 1:
5260     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5261     break;
5262   case 0xff:
5263     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5264     break;
5265   default:
5266     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5267     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5268   }
5269
5270   i ^= 1;
5271
5272   switch( BYTEofLONG(lit,i)) { 
5273   case 0:
5274     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5275     break;
5276   case 1:
5277     emitSKPNZ;
5278     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5279     break;
5280   case 0xff:
5281     emitSKPNZ;
5282     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5283     break;
5284   default:
5285     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5286     emitSKPNZ;
5287     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5288
5289   }
5290
5291 }
5292 #endif
5293
5294 #if 0
5295 // not needed ATM
5296 /*-----------------------------------------------------------------*/
5297 /* gencjneshort - compare and jump if not equal                    */
5298 /*-----------------------------------------------------------------*/
5299 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5300 {
5301   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5302   int offset = 0;
5303   int res_offset = 0;  /* the result may be a different size then left or right */
5304   int res_size = AOP_SIZE(result);
5305   resolvedIfx rIfx;
5306   symbol *lbl, *lbl_done;
5307
5308   unsigned long lit = 0L;
5309   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5310
5311   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5312   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5313   if(result)
5314     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5315   resolveIfx(&rIfx,ifx);
5316   lbl =  newiTempLabel(NULL);
5317   lbl_done =  newiTempLabel(NULL);
5318
5319
5320   /* if the left side is a literal or 
5321      if the right is in a pointer register and left 
5322      is not */
5323   if ((AOP_TYPE(left) == AOP_LIT) || 
5324       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5325     operand *t = right;
5326     right = left;
5327     left = t;
5328   }
5329   if(AOP_TYPE(right) == AOP_LIT)
5330     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5331
5332   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5333     preserve_result = 1;
5334
5335   if(result && !preserve_result)
5336     {
5337       int i;
5338       for(i = 0; i < AOP_SIZE(result); i++)
5339         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5340     }
5341
5342
5343   /* if the right side is a literal then anything goes */
5344   if (AOP_TYPE(right) == AOP_LIT &&
5345       AOP_TYPE(left) != AOP_DIR ) {
5346     switch(size) {
5347     case 2:
5348       genc16bit2lit(left, lit, 0);
5349       emitSKPZ;
5350       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5351       break;
5352     default:
5353       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5354       while (size--) {
5355         if(lit & 0xff) {
5356           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5357           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5358         } else {
5359           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5360         }
5361
5362         emitSKPZ;
5363         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5364         offset++;
5365         if(res_offset < res_size-1)
5366           res_offset++;
5367         lit >>= 8;
5368       }
5369       break;
5370     }
5371   }
5372
5373   /* if the right side is in a register or in direct space or
5374      if the left is a pointer register & right is not */    
5375   else if (AOP_TYPE(right) == AOP_REG ||
5376            AOP_TYPE(right) == AOP_DIR || 
5377            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5378            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5379     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5380     int lbl_key = lbl->key;
5381
5382     if(result) {
5383       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5384       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5385     }else {
5386       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5387       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5388               __FUNCTION__,__LINE__);
5389       return;
5390     }
5391    
5392 /*     switch(size) { */
5393 /*     case 2: */
5394 /*       genc16bit2lit(left, lit, 0); */
5395 /*       emitSKPNZ; */
5396 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5397 /*       break; */
5398 /*     default: */
5399     while (size--) {
5400       int emit_skip=1;
5401       if((AOP_TYPE(left) == AOP_DIR) && 
5402          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5403
5404         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5405         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5406
5407       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5408             
5409         switch (lit & 0xff) {
5410         case 0:
5411           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5412           break;
5413         case 1:
5414           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5415           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5416           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5417           emit_skip=0;
5418           break;
5419         case 0xff:
5420           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5421           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5422           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5423           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5424           emit_skip=0;
5425           break;
5426         default:
5427           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5428           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5429         }
5430         lit >>= 8;
5431
5432       } else {
5433         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5434       }
5435       if(emit_skip) {
5436         if(AOP_TYPE(result) == AOP_CRY) {
5437           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5438           if(rIfx.condition)
5439             emitSKPNZ;
5440           else
5441             emitSKPZ;
5442           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5443         } else {
5444           /* fix me. probably need to check result size too */
5445           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5446           if(rIfx.condition)
5447             emitSKPZ;
5448           else
5449             emitSKPNZ;
5450           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5451           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5452         }
5453         if(ifx)
5454           ifx->generated=1;
5455       }
5456       emit_skip++;
5457       offset++;
5458       if(res_offset < res_size-1)
5459         res_offset++;
5460     }
5461 /*       break; */
5462 /*     } */
5463   } else if(AOP_TYPE(right) == AOP_REG &&
5464             AOP_TYPE(left) != AOP_DIR){
5465
5466     while(size--) {
5467       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5468       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5469       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5470       if(rIfx.condition)
5471         emitSKPNZ;
5472       else
5473         emitSKPZ;
5474       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5475       offset++;
5476       if(res_offset < res_size-1)
5477         res_offset++;
5478     }
5479       
5480   }else{
5481     /* right is a pointer reg need both a & b */
5482     while(size--) {
5483       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5484       if(strcmp(l,"b"))
5485         pic16_emitcode("mov","b,%s",l);
5486       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5487       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5488       offset++;
5489     }
5490   }
5491
5492   if(result && preserve_result)
5493     {
5494       int i;
5495       for(i = 0; i < AOP_SIZE(result); i++)
5496         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5497     }
5498
5499   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5500
5501   if(result && preserve_result)
5502     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5503
5504   if(!rIfx.condition)
5505     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5506
5507   pic16_emitpLabel(lbl->key);
5508
5509   if(result && preserve_result)
5510     {
5511       int i;
5512       for(i = 0; i < AOP_SIZE(result); i++)
5513         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5514
5515       pic16_emitpLabel(lbl_done->key);
5516    }
5517
5518   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5519
5520   if(ifx)
5521     ifx->generated = 1;
5522 }
5523 #endif
5524
5525 #if 0
5526 /*-----------------------------------------------------------------*/
5527 /* gencjne - compare and jump if not equal                         */
5528 /*-----------------------------------------------------------------*/
5529 static void gencjne(operand *left, operand *right, iCode *ifx)
5530 {
5531     symbol *tlbl  = newiTempLabel(NULL);
5532
5533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5534     gencjneshort(left, right, lbl);
5535
5536     pic16_emitcode("mov","a,%s",one);
5537     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5538     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5539     pic16_emitcode("clr","a");
5540     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5541
5542     pic16_emitpLabel(lbl->key);
5543     pic16_emitpLabel(tlbl->key);
5544
5545 }
5546 #endif
5547
5548
5549 /*-----------------------------------------------------------------*/
5550 /* is_LitOp - check if operand has to be treated as literal        */
5551 /*-----------------------------------------------------------------*/
5552 static bool is_LitOp(operand *op)
5553 {
5554   return (AOP_TYPE(op) == AOP_LIT)
5555       || ( (AOP_TYPE(op) == AOP_PCODE)
5556           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5557               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5558 }
5559
5560
5561 /*-----------------------------------------------------------------*/
5562 /* genCmpEq - generates code for equal to                          */
5563 /*-----------------------------------------------------------------*/
5564 static void genCmpEq (iCode *ic, iCode *ifx)
5565 {
5566   operand *left, *right, *result;
5567   symbol *falselbl = newiTempLabel(NULL);
5568   symbol *donelbl = newiTempLabel(NULL);
5569
5570   int preserve_result = 0;
5571   int generate_result = 0;
5572   int i=0;
5573
5574   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5575   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5576   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5577  
5578   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5579   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5580
5581   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5582     {
5583       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5584       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5585       goto release;
5586     }
5587
5588   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5589     {
5590       operand *tmp = right ;
5591       right = left;
5592       left = tmp;
5593     }
5594
5595   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5596     preserve_result = 1;
5597
5598   if(result && AOP_SIZE(result))
5599     generate_result = 1;
5600
5601   if(generate_result && !preserve_result)
5602     {
5603       for(i = 0; i < AOP_SIZE(result); i++)
5604         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5605     }
5606
5607   for(i=0; i < AOP_SIZE(left); i++)
5608     {
5609       if(AOP_TYPE(left) != AOP_ACC)
5610         {
5611           if(is_LitOp(left))
5612             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5613           else
5614             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5615         }
5616       if(is_LitOp(right))
5617         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5618       else
5619         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5620
5621       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5622     }
5623
5624   // result == true
5625
5626   if(generate_result && preserve_result)
5627     {
5628       for(i = 0; i < AOP_SIZE(result); i++)
5629         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5630     }
5631
5632   if(generate_result)
5633     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5634
5635   if(generate_result && preserve_result)
5636     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5637
5638   if(ifx && IC_TRUE(ifx))
5639     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5640
5641   if(ifx && IC_FALSE(ifx))
5642     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5643
5644   pic16_emitpLabel(falselbl->key);
5645
5646   // result == false
5647
5648   if(ifx && IC_FALSE(ifx))
5649     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5650
5651   if(generate_result && preserve_result)
5652     {
5653       for(i = 0; i < AOP_SIZE(result); i++)
5654         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5655     }
5656
5657   pic16_emitpLabel(donelbl->key);
5658
5659   if(ifx)
5660     ifx->generated = 1;
5661
5662 release:
5663   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5664   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5665   pic16_freeAsmop(result,NULL,ic,TRUE);
5666
5667 }
5668
5669
5670 #if 0
5671 // old version kept for reference
5672
5673 /*-----------------------------------------------------------------*/
5674 /* genCmpEq - generates code for equal to                          */
5675 /*-----------------------------------------------------------------*/
5676 static void genCmpEq (iCode *ic, iCode *ifx)
5677 {
5678     operand *left, *right, *result;
5679     unsigned long lit = 0L;
5680     int size,offset=0;
5681     symbol *falselbl  = newiTempLabel(NULL);
5682
5683
5684     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5685
5686     if(ifx)
5687       DEBUGpic16_emitcode ("; ifx is non-null","");
5688     else
5689       DEBUGpic16_emitcode ("; ifx is null","");
5690
5691     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5692     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5693     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5694
5695     size = max(AOP_SIZE(left),AOP_SIZE(right));
5696
5697     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5698
5699     /* if literal, literal on the right or 
5700     if the right is in a pointer register and left 
5701     is not */
5702     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5703         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5704       operand *tmp = right ;
5705       right = left;
5706       left = tmp;
5707     }
5708
5709
5710     if(ifx && !AOP_SIZE(result)){
5711         symbol *tlbl;
5712         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5713         /* if they are both bit variables */
5714         if (AOP_TYPE(left) == AOP_CRY &&
5715             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5716                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5717             if(AOP_TYPE(right) == AOP_LIT){
5718                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5719                 if(lit == 0L){
5720                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5721                     pic16_emitcode("cpl","c");
5722                 } else if(lit == 1L) {
5723                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5724                 } else {
5725                     pic16_emitcode("clr","c");
5726                 }
5727                 /* AOP_TYPE(right) == AOP_CRY */
5728             } else {
5729                 symbol *lbl = newiTempLabel(NULL);
5730                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5731                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5732                 pic16_emitcode("cpl","c");
5733                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5734             }
5735             /* if true label then we jump if condition
5736             supplied is true */
5737             tlbl = newiTempLabel(NULL);
5738             if ( IC_TRUE(ifx) ) {
5739                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5740                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5741             } else {
5742                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5743                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5744             }
5745             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5746
5747                 {
5748                 /* left and right are both bit variables, result is carry */
5749                         resolvedIfx rIfx;
5750               
5751                         resolveIfx(&rIfx,ifx);
5752
5753                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5754                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5755                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5756                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5757                         genSkipz2(&rIfx,0);
5758                 }
5759         } else {
5760
5761                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5762
5763                         /* They're not both bit variables. Is the right a literal? */
5764                         if(AOP_TYPE(right) == AOP_LIT) {
5765                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5766             
5767                         switch(size) {
5768
5769                                 case 1:
5770                                         switch(lit & 0xff) {
5771                                                 case 1:
5772                                                                 if ( IC_TRUE(ifx) ) {
5773                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5774                                                                         emitSKPNZ;
5775                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5776                                                                 } else {
5777                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5778                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5779                                                                 }
5780                                                                 break;
5781                                                 case 0xff:
5782                                                                 if ( IC_TRUE(ifx) ) {
5783                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5784                                                                         emitSKPNZ;
5785                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5786                                                                 } else {
5787                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5788                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5789                                                                 }
5790                                                                 break;
5791                                                 default:
5792                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5793                                                                 if(lit)
5794                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5795                                                                 genSkip(ifx,'z');
5796                                         } // switch lit
5797
5798
5799                                         /* end of size == 1 */
5800                                         break;
5801               
5802                                 case 2:
5803                                         genc16bit2lit(left,lit,offset);
5804                                         genSkip(ifx,'z');
5805                                         break;
5806                                         /* end of size == 2 */
5807
5808                                 default:
5809                                         /* size is 4 */
5810                                         if(lit==0) {
5811                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5812                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5813                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5814                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5815                                                 genSkip(ifx,'z');
5816                                         } else {
5817                                                 /* search for patterns that can be optimized */
5818
5819                                                 genc16bit2lit(left,lit,0);
5820                                                 lit >>= 16;
5821                                                 if(lit) {
5822                                                                 if(IC_TRUE(ifx))
5823                                                                 emitSKPZ; // if hi word unequal
5824                                                                 else
5825                                                                 emitSKPNZ; // if hi word equal
5826                                                                 // fail early
5827                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5828                                                         genc16bit2lit(left,lit,2);
5829                                                         genSkip(ifx,'z');
5830                                                 } else {
5831                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5832                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5833                                                         genSkip(ifx,'z');
5834                                                 }
5835                                         }
5836                                                 pic16_emitpLabel(falselbl->key);
5837                                                 break;
5838
5839                         } // switch size
5840           
5841                         ifx->generated = 1;
5842                         goto release ;
5843             
5844
5845           } else if(AOP_TYPE(right) == AOP_CRY ) {
5846             /* we know the left is not a bit, but that the right is */
5847             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5848             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5849                       pic16_popGet(AOP(right),offset));
5850             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5851
5852             /* if the two are equal, then W will be 0 and the Z bit is set
5853              * we could test Z now, or go ahead and check the high order bytes if
5854              * the variable we're comparing is larger than a byte. */
5855
5856             while(--size)
5857               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5858
5859             if ( IC_TRUE(ifx) ) {
5860               emitSKPNZ;
5861               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5862               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5863             } else {
5864               emitSKPZ;
5865               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5866               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5867             }
5868
5869           } else {
5870             /* They're both variables that are larger than bits */
5871             int s = size;
5872
5873             tlbl = newiTempLabel(NULL);
5874
5875             while(size--) {
5876               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5877               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5878
5879               if ( IC_TRUE(ifx) ) {
5880                 if(size) {
5881                   emitSKPZ;
5882                 
5883                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5884
5885                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5886                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5887                 } else {
5888                   emitSKPNZ;
5889
5890                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5891
5892
5893                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5894                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5895                 }
5896               } else {
5897                 emitSKPZ;
5898
5899                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5900
5901                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5902                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5903               }
5904               offset++;
5905             }
5906             if(s>1 && IC_TRUE(ifx)) {
5907               pic16_emitpLabel(tlbl->key);
5908               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5909             }
5910           }
5911         }
5912         /* mark the icode as generated */
5913         ifx->generated = 1;
5914         goto release ;
5915     }
5916
5917     /* if they are both bit variables */
5918     if (AOP_TYPE(left) == AOP_CRY &&
5919         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5920         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5921         if(AOP_TYPE(right) == AOP_LIT){
5922             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5923             if(lit == 0L){
5924                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5925                 pic16_emitcode("cpl","c");
5926             } else if(lit == 1L) {
5927                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5928             } else {
5929                 pic16_emitcode("clr","c");
5930             }
5931             /* AOP_TYPE(right) == AOP_CRY */
5932         } else {
5933             symbol *lbl = newiTempLabel(NULL);
5934             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5935             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5936             pic16_emitcode("cpl","c");
5937             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5938         }
5939         /* c = 1 if egal */
5940         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5941             pic16_outBitC(result);
5942             goto release ;
5943         }
5944         if (ifx) {
5945             genIfxJump (ifx,"c");
5946             goto release ;
5947         }
5948         /* if the result is used in an arithmetic operation
5949         then put the result in place */
5950         pic16_outBitC(result);
5951     } else {
5952       
5953       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5954       gencjne(left,right,result,ifx);
5955 /*
5956       if(ifx) 
5957         gencjne(left,right,newiTempLabel(NULL));
5958       else {
5959         if(IC_TRUE(ifx)->key)
5960           gencjne(left,right,IC_TRUE(ifx)->key);
5961         else
5962           gencjne(left,right,IC_FALSE(ifx)->key);
5963         ifx->generated = 1;
5964         goto release ;
5965       }
5966       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5967         pic16_aopPut(AOP(result),"a",0);
5968         goto release ;
5969       }
5970
5971       if (ifx) {
5972         genIfxJump (ifx,"a");
5973         goto release ;
5974       }
5975 */
5976       /* if the result is used in an arithmetic operation
5977          then put the result in place */
5978 /*
5979       if (AOP_TYPE(result) != AOP_CRY) 
5980         pic16_outAcc(result);
5981 */
5982       /* leave the result in acc */
5983     }
5984
5985 release:
5986     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5987     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5988     pic16_freeAsmop(result,NULL,ic,TRUE);
5989 }
5990 #endif
5991
5992 /*-----------------------------------------------------------------*/
5993 /* ifxForOp - returns the icode containing the ifx for operand     */
5994 /*-----------------------------------------------------------------*/
5995 static iCode *ifxForOp ( operand *op, iCode *ic )
5996 {
5997     /* if true symbol then needs to be assigned */
5998     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5999     if (IS_TRUE_SYMOP(op))
6000         return NULL ;
6001
6002     /* if this has register type condition and
6003     the next instruction is ifx with the same operand
6004     and live to of the operand is upto the ifx only then */
6005     if (ic->next &&
6006         ic->next->op == IFX &&
6007         IC_COND(ic->next)->key == op->key &&
6008         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6009         return ic->next;
6010
6011     if (ic->next &&
6012         ic->next->op == IFX &&
6013         IC_COND(ic->next)->key == op->key) {
6014       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6015       return ic->next;
6016     }
6017
6018     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6019     if (ic->next &&
6020         ic->next->op == IFX)
6021       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6022
6023     if (ic->next &&
6024         ic->next->op == IFX &&
6025         IC_COND(ic->next)->key == op->key) {
6026       DEBUGpic16_emitcode ("; "," key is okay");
6027       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6028                            OP_SYMBOL(op)->liveTo,
6029                            ic->next->seq);
6030     }
6031
6032 #if 0
6033     /* the code below is completely untested
6034      * it just allows ulong2fs.c compile -- VR */
6035          
6036     ic = ic->next;
6037     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6038                                         __FILE__, __FUNCTION__, __LINE__);
6039         
6040     /* if this has register type condition and
6041     the next instruction is ifx with the same operand
6042     and live to of the operand is upto the ifx only then */
6043     if (ic->next &&
6044         ic->next->op == IFX &&
6045         IC_COND(ic->next)->key == op->key &&
6046         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6047         return ic->next;
6048
6049     if (ic->next &&
6050         ic->next->op == IFX &&
6051         IC_COND(ic->next)->key == op->key) {
6052       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6053       return ic->next;
6054     }
6055
6056     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6057                                         __FILE__, __FUNCTION__, __LINE__);
6058
6059 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6060 #endif
6061     return NULL;
6062 }
6063 /*-----------------------------------------------------------------*/
6064 /* genAndOp - for && operation                                     */
6065 /*-----------------------------------------------------------------*/
6066 static void genAndOp (iCode *ic)
6067 {
6068     operand *left,*right, *result;
6069 /*     symbol *tlbl; */
6070
6071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6072     /* note here that && operations that are in an
6073     if statement are taken away by backPatchLabels
6074     only those used in arthmetic operations remain */
6075     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6076     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6077     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6078
6079     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6080
6081     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6082     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6083     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6084
6085     /* if both are bit variables */
6086 /*     if (AOP_TYPE(left) == AOP_CRY && */
6087 /*         AOP_TYPE(right) == AOP_CRY ) { */
6088 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6089 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6090 /*         pic16_outBitC(result); */
6091 /*     } else { */
6092 /*         tlbl = newiTempLabel(NULL); */
6093 /*         pic16_toBoolean(left);     */
6094 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6095 /*         pic16_toBoolean(right); */
6096 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6097 /*         pic16_outBitAcc(result); */
6098 /*     } */
6099
6100     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6101     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6102     pic16_freeAsmop(result,NULL,ic,TRUE);
6103 }
6104
6105
6106 /*-----------------------------------------------------------------*/
6107 /* genOrOp - for || operation                                      */
6108 /*-----------------------------------------------------------------*/
6109 /*
6110   tsd pic port -
6111   modified this code, but it doesn't appear to ever get called
6112 */
6113
6114 static void genOrOp (iCode *ic)
6115 {
6116     operand *left,*right, *result;
6117     symbol *tlbl;
6118
6119     /* note here that || operations that are in an
6120     if statement are taken away by backPatchLabels
6121     only those used in arthmetic operations remain */
6122     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6123     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6124     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6125     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6126
6127     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6128
6129     /* if both are bit variables */
6130     if (AOP_TYPE(left) == AOP_CRY &&
6131         AOP_TYPE(right) == AOP_CRY ) {
6132       pic16_emitcode("clrc","");
6133       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6134                AOP(left)->aopu.aop_dir,
6135                AOP(left)->aopu.aop_dir);
6136       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6137                AOP(right)->aopu.aop_dir,
6138                AOP(right)->aopu.aop_dir);
6139       pic16_emitcode("setc","");
6140
6141     } else {
6142         tlbl = newiTempLabel(NULL);
6143         pic16_toBoolean(left);
6144         emitSKPZ;
6145         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6146         pic16_toBoolean(right);
6147         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6148
6149         pic16_outBitAcc(result);
6150     }
6151
6152     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6153     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6154     pic16_freeAsmop(result,NULL,ic,TRUE);            
6155 }
6156
6157 /*-----------------------------------------------------------------*/
6158 /* isLiteralBit - test if lit == 2^n                               */
6159 /*-----------------------------------------------------------------*/
6160 static int isLiteralBit(unsigned long lit)
6161 {
6162     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6163     0x100L,0x200L,0x400L,0x800L,
6164     0x1000L,0x2000L,0x4000L,0x8000L,
6165     0x10000L,0x20000L,0x40000L,0x80000L,
6166     0x100000L,0x200000L,0x400000L,0x800000L,
6167     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6168     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6169     int idx;
6170     
6171     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6172     for(idx = 0; idx < 32; idx++)
6173         if(lit == pw[idx])
6174             return idx+1;
6175     return 0;
6176 }
6177
6178 /*-----------------------------------------------------------------*/
6179 /* continueIfTrue -                                                */
6180 /*-----------------------------------------------------------------*/
6181 static void continueIfTrue (iCode *ic)
6182 {
6183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6184     if(IC_TRUE(ic))
6185         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6186     ic->generated = 1;
6187 }
6188
6189 /*-----------------------------------------------------------------*/
6190 /* jmpIfTrue -                                                     */
6191 /*-----------------------------------------------------------------*/
6192 static void jumpIfTrue (iCode *ic)
6193 {
6194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6195     if(!IC_TRUE(ic))
6196         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6197     ic->generated = 1;
6198 }
6199
6200 /*-----------------------------------------------------------------*/
6201 /* jmpTrueOrFalse -                                                */
6202 /*-----------------------------------------------------------------*/
6203 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6204 {
6205     // ugly but optimized by peephole
6206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6207     if(IC_TRUE(ic)){
6208         symbol *nlbl = newiTempLabel(NULL);
6209         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6210         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6211         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6212         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6213     }
6214     else{
6215         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6216         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6217     }
6218     ic->generated = 1;
6219 }
6220
6221 /*-----------------------------------------------------------------*/
6222 /* genAnd  - code for and                                          */
6223 /*-----------------------------------------------------------------*/
6224 static void genAnd (iCode *ic, iCode *ifx)
6225 {
6226   operand *left, *right, *result;
6227   int size, offset=0;  
6228   unsigned long lit = 0L;
6229   int bytelit = 0;
6230   resolvedIfx rIfx;
6231
6232
6233   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6234   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6235   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6236   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6237
6238   resolveIfx(&rIfx,ifx);
6239
6240   /* if left is a literal & right is not then exchange them */
6241   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6242       AOP_NEEDSACC(left)) {
6243     operand *tmp = right ;
6244     right = left;
6245     left = tmp;
6246   }
6247
6248   /* if result = right then exchange them */
6249   if(pic16_sameRegs(AOP(result),AOP(right))){
6250     operand *tmp = right ;
6251     right = left;
6252     left = tmp;
6253   }
6254
6255   /* if right is bit then exchange them */
6256   if (AOP_TYPE(right) == AOP_CRY &&
6257       AOP_TYPE(left) != AOP_CRY){
6258     operand *tmp = right ;
6259     right = left;
6260     left = tmp;
6261   }
6262   if(AOP_TYPE(right) == AOP_LIT)
6263     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6264
6265   size = AOP_SIZE(result);
6266
6267   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6268
6269   // if(bit & yy)
6270   // result = bit & yy;
6271   if (AOP_TYPE(left) == AOP_CRY){
6272     // c = bit & literal;
6273     if(AOP_TYPE(right) == AOP_LIT){
6274       if(lit & 1) {
6275         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6276           // no change
6277           goto release;
6278         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6279       } else {
6280         // bit(result) = 0;
6281         if(size && (AOP_TYPE(result) == AOP_CRY)){
6282           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6283           goto release;
6284         }
6285         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6286           jumpIfTrue(ifx);
6287           goto release;
6288         }
6289         pic16_emitcode("clr","c");
6290       }
6291     } else {
6292       if (AOP_TYPE(right) == AOP_CRY){
6293         // c = bit & bit;
6294         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6295         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6296       } else {
6297         // c = bit & val;
6298         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6299         // c = lsb
6300         pic16_emitcode("rrc","a");
6301         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6302       }
6303     }
6304     // bit = c
6305     // val = c
6306     if(size)
6307       pic16_outBitC(result);
6308     // if(bit & ...)
6309     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6310       genIfxJump(ifx, "c");           
6311     goto release ;
6312   }
6313
6314   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6315   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6316   if((AOP_TYPE(right) == AOP_LIT) &&
6317      (AOP_TYPE(result) == AOP_CRY) &&
6318      (AOP_TYPE(left) != AOP_CRY)){
6319     int posbit = isLiteralBit(lit);
6320     /* left &  2^n */
6321     if(posbit){
6322       posbit--;
6323       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6324       // bit = left & 2^n
6325       if(size)
6326         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6327       // if(left &  2^n)
6328       else{
6329         if(ifx){
6330 /*
6331           if(IC_TRUE(ifx)) {
6332             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6333             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6334           } else {
6335             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6336             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6337           }
6338 */
6339           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6340                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6341           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6342           
6343           ifx->generated = 1;
6344         }
6345         goto release;
6346       }
6347     } else {
6348       symbol *tlbl = newiTempLabel(NULL);
6349       int sizel = AOP_SIZE(left);
6350       if(size)
6351         pic16_emitcode("setb","c");
6352       while(sizel--){
6353         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6354           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6355           // byte ==  2^n ?
6356           if((posbit = isLiteralBit(bytelit)) != 0)
6357             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6358           else{
6359             if(bytelit != 0x0FFL)
6360               pic16_emitcode("anl","a,%s",
6361                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6362             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6363           }
6364         }
6365         offset++;
6366       }
6367       // bit = left & literal
6368       if(size){
6369         pic16_emitcode("clr","c");
6370         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6371       }
6372       // if(left & literal)
6373       else{
6374         if(ifx)
6375           jmpTrueOrFalse(ifx, tlbl);
6376         goto release ;
6377       }
6378     }
6379     pic16_outBitC(result);
6380     goto release ;
6381   }
6382
6383   /* if left is same as result */
6384   if(pic16_sameRegs(AOP(result),AOP(left))){
6385     int know_W = -1;
6386     for(;size--; offset++,lit>>=8) {
6387       if(AOP_TYPE(right) == AOP_LIT){
6388         switch(lit & 0xff) {
6389         case 0x00:
6390           /*  and'ing with 0 has clears the result */
6391 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6392           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6393           break;
6394         case 0xff:
6395           /* and'ing with 0xff is a nop when the result and left are the same */
6396           break;
6397
6398         default:
6399           {
6400             int p = my_powof2( (~lit) & 0xff );
6401             if(p>=0) {
6402               /* only one bit is set in the literal, so use a bcf instruction */
6403 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6404               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6405
6406             } else {
6407               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6408               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6409               if(know_W != (lit&0xff))
6410                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6411               know_W = lit &0xff;
6412               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6413             }
6414           }    
6415         }
6416       } else {
6417         if (AOP_TYPE(left) == AOP_ACC) {
6418           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6419         } else {                    
6420           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6421           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6422
6423         }
6424       }
6425     }
6426
6427   } else {
6428     // left & result in different registers
6429     if(AOP_TYPE(result) == AOP_CRY){
6430       // result = bit
6431       // if(size), result in bit
6432       // if(!size && ifx), conditional oper: if(left & right)
6433       symbol *tlbl = newiTempLabel(NULL);
6434       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6435       if(size)
6436         pic16_emitcode("setb","c");
6437       while(sizer--){
6438         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6439         pic16_emitcode("anl","a,%s",
6440                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6441         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6442         offset++;
6443       }
6444       if(size){
6445         CLRC;
6446         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6447         pic16_outBitC(result);
6448       } else if(ifx)
6449         jmpTrueOrFalse(ifx, tlbl);
6450     } else {
6451       for(;(size--);offset++) {
6452         // normal case
6453         // result = left & right
6454         if(AOP_TYPE(right) == AOP_LIT){
6455           int t = (lit >> (offset*8)) & 0x0FFL;
6456           switch(t) { 
6457           case 0x00:
6458             pic16_emitcode("clrf","%s",
6459                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6460             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6461             break;
6462           case 0xff:
6463             pic16_emitcode("movf","%s,w",
6464                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6465             pic16_emitcode("movwf","%s",
6466                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6467             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6468             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6469             break;
6470           default:
6471             pic16_emitcode("movlw","0x%x",t);
6472             pic16_emitcode("andwf","%s,w",
6473                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6474             pic16_emitcode("movwf","%s",
6475                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6476               
6477             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6478             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6479             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6480           }
6481           continue;
6482         }
6483
6484         if (AOP_TYPE(left) == AOP_ACC) {
6485           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6486           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6487         } else {
6488           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6489           pic16_emitcode("andwf","%s,w",
6490                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6491           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6492           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6493         }
6494         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6495         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6496       }
6497     }
6498   }
6499
6500   release :
6501     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6502   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6503   pic16_freeAsmop(result,NULL,ic,TRUE);     
6504 }
6505
6506 /*-----------------------------------------------------------------*/
6507 /* genOr  - code for or                                            */
6508 /*-----------------------------------------------------------------*/
6509 static void genOr (iCode *ic, iCode *ifx)
6510 {
6511     operand *left, *right, *result;
6512     int size, offset=0;
6513     unsigned long lit = 0L;
6514
6515     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6516
6517     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6518     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6519     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6520
6521     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6522
6523     /* if left is a literal & right is not then exchange them */
6524     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6525         AOP_NEEDSACC(left)) {
6526         operand *tmp = right ;
6527         right = left;
6528         left = tmp;
6529     }
6530
6531     /* if result = right then exchange them */
6532     if(pic16_sameRegs(AOP(result),AOP(right))){
6533         operand *tmp = right ;
6534         right = left;
6535         left = tmp;
6536     }
6537
6538     /* if right is bit then exchange them */
6539     if (AOP_TYPE(right) == AOP_CRY &&
6540         AOP_TYPE(left) != AOP_CRY){
6541         operand *tmp = right ;
6542         right = left;
6543         left = tmp;
6544     }
6545
6546     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6547
6548     if(AOP_TYPE(right) == AOP_LIT)
6549         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6550
6551     size = AOP_SIZE(result);
6552
6553     // if(bit | yy)
6554     // xx = bit | yy;
6555     if (AOP_TYPE(left) == AOP_CRY){
6556         if(AOP_TYPE(right) == AOP_LIT){
6557             // c = bit & literal;
6558             if(lit){
6559                 // lit != 0 => result = 1
6560                 if(AOP_TYPE(result) == AOP_CRY){
6561                   if(size)
6562                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6563                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6564                   //     AOP(result)->aopu.aop_dir,
6565                   //     AOP(result)->aopu.aop_dir);
6566                     else if(ifx)
6567                         continueIfTrue(ifx);
6568                     goto release;
6569                 }
6570             } else {
6571                 // lit == 0 => result = left
6572                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6573                     goto release;
6574                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6575             }
6576         } else {
6577             if (AOP_TYPE(right) == AOP_CRY){
6578               if(pic16_sameRegs(AOP(result),AOP(left))){
6579                 // c = bit | bit;
6580                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6581                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6582                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6583
6584                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6585                          AOP(result)->aopu.aop_dir,
6586                          AOP(result)->aopu.aop_dir);
6587                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6588                          AOP(right)->aopu.aop_dir,
6589                          AOP(right)->aopu.aop_dir);
6590                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6591                          AOP(result)->aopu.aop_dir,
6592                          AOP(result)->aopu.aop_dir);
6593               } else {
6594                 if( AOP_TYPE(result) == AOP_ACC) {
6595                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6596                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6597                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6598                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6599
6600                 } else {
6601
6602                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6603                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6604                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6605                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6606
6607                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6608                                  AOP(result)->aopu.aop_dir,
6609                                  AOP(result)->aopu.aop_dir);
6610                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6611                                  AOP(right)->aopu.aop_dir,
6612                                  AOP(right)->aopu.aop_dir);
6613                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6614                                  AOP(left)->aopu.aop_dir,
6615                                  AOP(left)->aopu.aop_dir);
6616                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6617                                  AOP(result)->aopu.aop_dir,
6618                                  AOP(result)->aopu.aop_dir);
6619                 }
6620               }
6621             } else {
6622                 // c = bit | val;
6623                 symbol *tlbl = newiTempLabel(NULL);
6624                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6625
6626
6627                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6628                 if( AOP_TYPE(right) == AOP_ACC) {
6629                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6630                   emitSKPNZ;
6631                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6632                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6633                 }
6634
6635
6636
6637                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6638                     pic16_emitcode(";XXX setb","c");
6639                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6640                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6641                 pic16_toBoolean(right);
6642                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6643                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6644                     jmpTrueOrFalse(ifx, tlbl);
6645                     goto release;
6646                 } else {
6647                     CLRC;
6648                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6649                 }
6650             }
6651         }
6652         // bit = c
6653         // val = c
6654         if(size)
6655             pic16_outBitC(result);
6656         // if(bit | ...)
6657         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6658             genIfxJump(ifx, "c");           
6659         goto release ;
6660     }
6661
6662     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6663     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6664     if((AOP_TYPE(right) == AOP_LIT) &&
6665        (AOP_TYPE(result) == AOP_CRY) &&
6666        (AOP_TYPE(left) != AOP_CRY)){
6667         if(lit){
6668           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6669             // result = 1
6670             if(size)
6671                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6672             else 
6673                 continueIfTrue(ifx);
6674             goto release;
6675         } else {
6676           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6677             // lit = 0, result = boolean(left)
6678             if(size)
6679                 pic16_emitcode(";XXX setb","c");
6680             pic16_toBoolean(right);
6681             if(size){
6682                 symbol *tlbl = newiTempLabel(NULL);
6683                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6684                 CLRC;
6685                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6686             } else {
6687                 genIfxJump (ifx,"a");
6688                 goto release;
6689             }
6690         }
6691         pic16_outBitC(result);
6692         goto release ;
6693     }
6694
6695     /* if left is same as result */
6696     if(pic16_sameRegs(AOP(result),AOP(left))){
6697       int know_W = -1;
6698       for(;size--; offset++,lit>>=8) {
6699         if(AOP_TYPE(right) == AOP_LIT){
6700           if((lit & 0xff) == 0)
6701             /*  or'ing with 0 has no effect */
6702             continue;
6703           else {
6704             int p = my_powof2(lit & 0xff);
6705             if(p>=0) {
6706               /* only one bit is set in the literal, so use a bsf instruction */
6707               pic16_emitpcode(POC_BSF,
6708                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6709             } else {
6710               if(know_W != (lit & 0xff))
6711                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6712               know_W = lit & 0xff;
6713               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6714             }
6715                     
6716           }
6717         } else {
6718           if (AOP_TYPE(left) == AOP_ACC) {
6719             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6720             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6721           } else {                  
6722             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6723             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6724
6725             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6726             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6727
6728           }
6729         }
6730       }
6731     } else {
6732         // left & result in different registers
6733         if(AOP_TYPE(result) == AOP_CRY){
6734             // result = bit
6735             // if(size), result in bit
6736             // if(!size && ifx), conditional oper: if(left | right)
6737             symbol *tlbl = newiTempLabel(NULL);
6738             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6739             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6740
6741
6742             if(size)
6743                 pic16_emitcode(";XXX setb","c");
6744             while(sizer--){
6745                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6746                 pic16_emitcode(";XXX orl","a,%s",
6747                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6748                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6749                 offset++;
6750             }
6751             if(size){
6752                 CLRC;
6753                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6754                 pic16_outBitC(result);
6755             } else if(ifx)
6756                 jmpTrueOrFalse(ifx, tlbl);
6757         } else for(;(size--);offset++){
6758           // normal case
6759           // result = left & right
6760           if(AOP_TYPE(right) == AOP_LIT){
6761             int t = (lit >> (offset*8)) & 0x0FFL;
6762             switch(t) { 
6763             case 0x00:
6764               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6765               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6766
6767               pic16_emitcode("movf","%s,w",
6768                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6769               pic16_emitcode("movwf","%s",
6770                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6771               break;
6772             default:
6773               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6774               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6775               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6776
6777               pic16_emitcode("movlw","0x%x",t);
6778               pic16_emitcode("iorwf","%s,w",
6779                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6780               pic16_emitcode("movwf","%s",
6781                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6782               
6783             }
6784             continue;
6785           }
6786
6787           // faster than result <- left, anl result,right
6788           // and better if result is SFR
6789           if (AOP_TYPE(left) == AOP_ACC) {
6790             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6791             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6792           } else {
6793             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6794             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6795
6796             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6797             pic16_emitcode("iorwf","%s,w",
6798                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6799           }
6800           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6801           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6802         }
6803     }
6804
6805 release :
6806     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6807     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6808     pic16_freeAsmop(result,NULL,ic,TRUE);     
6809 }
6810
6811 /*-----------------------------------------------------------------*/
6812 /* genXor - code for xclusive or                                   */
6813 /*-----------------------------------------------------------------*/
6814 static void genXor (iCode *ic, iCode *ifx)
6815 {
6816   operand *left, *right, *result;
6817   int size, offset=0;
6818   unsigned long lit = 0L;
6819
6820   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6821
6822   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6823   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6824   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6825
6826   /* if left is a literal & right is not ||
6827      if left needs acc & right does not */
6828   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6829       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6830     operand *tmp = right ;
6831     right = left;
6832     left = tmp;
6833   }
6834
6835   /* if result = right then exchange them */
6836   if(pic16_sameRegs(AOP(result),AOP(right))){
6837     operand *tmp = right ;
6838     right = left;
6839     left = tmp;
6840   }
6841
6842   /* if right is bit then exchange them */
6843   if (AOP_TYPE(right) == AOP_CRY &&
6844       AOP_TYPE(left) != AOP_CRY){
6845     operand *tmp = right ;
6846     right = left;
6847     left = tmp;
6848   }
6849   if(AOP_TYPE(right) == AOP_LIT)
6850     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6851
6852   size = AOP_SIZE(result);
6853
6854   // if(bit ^ yy)
6855   // xx = bit ^ yy;
6856   if (AOP_TYPE(left) == AOP_CRY){
6857     if(AOP_TYPE(right) == AOP_LIT){
6858       // c = bit & literal;
6859       if(lit>>1){
6860         // lit>>1  != 0 => result = 1
6861         if(AOP_TYPE(result) == AOP_CRY){
6862           if(size)
6863             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6864             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6865           else if(ifx)
6866             continueIfTrue(ifx);
6867           goto release;
6868         }
6869         pic16_emitcode("setb","c");
6870       } else{
6871         // lit == (0 or 1)
6872         if(lit == 0){
6873           // lit == 0, result = left
6874           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6875             goto release;
6876           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6877         } else{
6878           // lit == 1, result = not(left)
6879           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6880             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6881             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6882             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6883             goto release;
6884           } else {
6885             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6886             pic16_emitcode("cpl","c");
6887           }
6888         }
6889       }
6890
6891     } else {
6892       // right != literal
6893       symbol *tlbl = newiTempLabel(NULL);
6894       if (AOP_TYPE(right) == AOP_CRY){
6895         // c = bit ^ bit;
6896         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6897       }
6898       else{
6899         int sizer = AOP_SIZE(right);
6900         // c = bit ^ val
6901         // if val>>1 != 0, result = 1
6902         pic16_emitcode("setb","c");
6903         while(sizer){
6904           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6905           if(sizer == 1)
6906             // test the msb of the lsb
6907             pic16_emitcode("anl","a,#0xfe");
6908           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6909           sizer--;
6910         }
6911         // val = (0,1)
6912         pic16_emitcode("rrc","a");
6913       }
6914       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6915       pic16_emitcode("cpl","c");
6916       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6917     }
6918     // bit = c
6919     // val = c
6920     if(size)
6921       pic16_outBitC(result);
6922     // if(bit | ...)
6923     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6924       genIfxJump(ifx, "c");           
6925     goto release ;
6926   }
6927
6928   if(pic16_sameRegs(AOP(result),AOP(left))){
6929     /* if left is same as result */
6930     for(;size--; offset++) {
6931       if(AOP_TYPE(right) == AOP_LIT){
6932         int t  = (lit >> (offset*8)) & 0x0FFL;
6933         if(t == 0x00L)
6934           continue;
6935         else
6936           if (IS_AOP_PREG(left)) {
6937             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6938             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6939             pic16_aopPut(AOP(result),"a",offset);
6940           } else {
6941             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6942             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6943             pic16_emitcode("xrl","%s,%s",
6944                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6945                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6946           }
6947       } else {
6948         if (AOP_TYPE(left) == AOP_ACC)
6949           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6950         else {
6951           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6952           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6953 /*
6954           if (IS_AOP_PREG(left)) {
6955             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6956             pic16_aopPut(AOP(result),"a",offset);
6957           } else
6958             pic16_emitcode("xrl","%s,a",
6959                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6960 */
6961         }
6962       }
6963     }
6964   } else {
6965     // left & result in different registers
6966     if(AOP_TYPE(result) == AOP_CRY){
6967       // result = bit
6968       // if(size), result in bit
6969       // if(!size && ifx), conditional oper: if(left ^ right)
6970       symbol *tlbl = newiTempLabel(NULL);
6971       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6972       if(size)
6973         pic16_emitcode("setb","c");
6974       while(sizer--){
6975         if((AOP_TYPE(right) == AOP_LIT) &&
6976            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6977           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6978         } else {
6979           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6980           pic16_emitcode("xrl","a,%s",
6981                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6982         }
6983         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6984         offset++;
6985       }
6986       if(size){
6987         CLRC;
6988         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6989         pic16_outBitC(result);
6990       } else if(ifx)
6991         jmpTrueOrFalse(ifx, tlbl);
6992     } else for(;(size--);offset++){
6993       // normal case
6994       // result = left & right
6995       if(AOP_TYPE(right) == AOP_LIT){
6996         int t = (lit >> (offset*8)) & 0x0FFL;
6997         switch(t) { 
6998         case 0x00:
6999           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7000           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7001           pic16_emitcode("movf","%s,w",
7002                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7003           pic16_emitcode("movwf","%s",
7004                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7005           break;
7006         case 0xff:
7007           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7008           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7009           pic16_emitcode("comf","%s,w",
7010                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7011           pic16_emitcode("movwf","%s",
7012                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7013           break;
7014         default:
7015           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7016           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7017           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7018           pic16_emitcode("movlw","0x%x",t);
7019           pic16_emitcode("xorwf","%s,w",
7020                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7021           pic16_emitcode("movwf","%s",
7022                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7023
7024         }
7025         continue;
7026       }
7027
7028       // faster than result <- left, anl result,right
7029       // and better if result is SFR
7030       if (AOP_TYPE(left) == AOP_ACC) {
7031         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7032         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7033       } else {
7034         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7035         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7036         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7037         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7038       }
7039       if ( AOP_TYPE(result) != AOP_ACC){
7040         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7041         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7042       }
7043     }
7044   }
7045
7046   release :
7047     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7048   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7049   pic16_freeAsmop(result,NULL,ic,TRUE);     
7050 }
7051
7052 /*-----------------------------------------------------------------*/
7053 /* genInline - write the inline code out                           */
7054 /*-----------------------------------------------------------------*/
7055 static void genInline (iCode *ic)
7056 {
7057   char *buffer, *bp, *bp1;
7058     
7059         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7060
7061         _G.inLine += (!options.asmpeep);
7062
7063         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7064         strcpy(buffer,IC_INLINE(ic));
7065
7066 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7067
7068         /* emit each line as a code */
7069         while (*bp) {
7070                 if (*bp == '\n') {
7071                         *bp++ = '\0';
7072
7073                         if(*bp1)
7074                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7075                         bp1 = bp;
7076                 } else {
7077                         if (*bp == ':') {
7078                                 bp++;
7079                                 *bp = '\0';
7080                                 bp++;
7081
7082                                 /* print label, use this special format with NULL directive
7083                                  * to denote that the argument should not be indented with tab */
7084                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7085                                 bp1 = bp;
7086                         } else
7087                                 bp++;
7088                 }
7089         }
7090
7091         if ((bp1 != bp) && *bp1)
7092                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7093
7094
7095     Safe_free(buffer);
7096
7097     _G.inLine -= (!options.asmpeep);
7098 }
7099
7100 /*-----------------------------------------------------------------*/
7101 /* genRRC - rotate right with carry                                */
7102 /*-----------------------------------------------------------------*/
7103 static void genRRC (iCode *ic)
7104 {
7105   operand *left , *result ;
7106   int size, offset = 0, same;
7107
7108   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7109
7110   /* rotate right with carry */
7111   left = IC_LEFT(ic);
7112   result=IC_RESULT(ic);
7113   pic16_aopOp (left,ic,FALSE);
7114   pic16_aopOp (result,ic,FALSE);
7115
7116   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7117
7118   same = pic16_sameRegs(AOP(result),AOP(left));
7119
7120   size = AOP_SIZE(result);    
7121
7122   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7123
7124   /* get the lsb and put it into the carry */
7125   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7126
7127   offset = 0 ;
7128
7129   while(size--) {
7130
7131     if(same) {
7132       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7133     } else {
7134       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7135       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7136     }
7137
7138     offset++;
7139   }
7140
7141   pic16_freeAsmop(left,NULL,ic,TRUE);
7142   pic16_freeAsmop(result,NULL,ic,TRUE);
7143 }
7144
7145 /*-----------------------------------------------------------------*/
7146 /* genRLC - generate code for rotate left with carry               */
7147 /*-----------------------------------------------------------------*/
7148 static void genRLC (iCode *ic)
7149 {    
7150   operand *left , *result ;
7151   int size, offset = 0;
7152   int same;
7153
7154   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7155   /* rotate right with carry */
7156   left = IC_LEFT(ic);
7157   result=IC_RESULT(ic);
7158   pic16_aopOp (left,ic,FALSE);
7159   pic16_aopOp (result,ic,FALSE);
7160
7161   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7162
7163   same = pic16_sameRegs(AOP(result),AOP(left));
7164
7165   /* move it to the result */
7166   size = AOP_SIZE(result);    
7167
7168   /* get the msb and put it into the carry */
7169   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7170
7171   offset = 0 ;
7172
7173   while(size--) {
7174
7175     if(same) {
7176       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7177     } else {
7178       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7179       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7180     }
7181
7182     offset++;
7183   }
7184
7185
7186   pic16_freeAsmop(left,NULL,ic,TRUE);
7187   pic16_freeAsmop(result,NULL,ic,TRUE);
7188 }
7189
7190
7191 /* gpasm can get the highest order bit with HIGH/UPPER
7192  * so the following probably is not needed -- VR */
7193  
7194 /*-----------------------------------------------------------------*/
7195 /* genGetHbit - generates code get highest order bit               */
7196 /*-----------------------------------------------------------------*/
7197 static void genGetHbit (iCode *ic)
7198 {
7199     operand *left, *result;
7200     left = IC_LEFT(ic);
7201     result=IC_RESULT(ic);
7202     pic16_aopOp (left,ic,FALSE);
7203     pic16_aopOp (result,ic,FALSE);
7204
7205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7206     /* get the highest order byte into a */
7207     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7208     if(AOP_TYPE(result) == AOP_CRY){
7209         pic16_emitcode("rlc","a");
7210         pic16_outBitC(result);
7211     }
7212     else{
7213         pic16_emitcode("rl","a");
7214         pic16_emitcode("anl","a,#0x01");
7215         pic16_outAcc(result);
7216     }
7217
7218
7219     pic16_freeAsmop(left,NULL,ic,TRUE);
7220     pic16_freeAsmop(result,NULL,ic,TRUE);
7221 }
7222
7223 #if 0
7224 /*-----------------------------------------------------------------*/
7225 /* AccRol - rotate left accumulator by known count                 */
7226 /*-----------------------------------------------------------------*/
7227 static void AccRol (int shCount)
7228 {
7229     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7230     shCount &= 0x0007;              // shCount : 0..7
7231     switch(shCount){
7232         case 0 :
7233             break;
7234         case 1 :
7235             pic16_emitcode("rl","a");
7236             break;
7237         case 2 :
7238             pic16_emitcode("rl","a");
7239             pic16_emitcode("rl","a");
7240             break;
7241         case 3 :
7242             pic16_emitcode("swap","a");
7243             pic16_emitcode("rr","a");
7244             break;
7245         case 4 :
7246             pic16_emitcode("swap","a");
7247             break;
7248         case 5 :
7249             pic16_emitcode("swap","a");
7250             pic16_emitcode("rl","a");
7251             break;
7252         case 6 :
7253             pic16_emitcode("rr","a");
7254             pic16_emitcode("rr","a");
7255             break;
7256         case 7 :
7257             pic16_emitcode("rr","a");
7258             break;
7259     }
7260 }
7261 #endif
7262
7263 /*-----------------------------------------------------------------*/
7264 /* AccLsh - left shift accumulator by known count                  */
7265 /*-----------------------------------------------------------------*/
7266 static void AccLsh (int shCount)
7267 {
7268         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7269         switch(shCount){
7270                 case 0 :
7271                         return;
7272                         break;
7273                 case 1 :
7274                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7275                         break;
7276                 case 2 :
7277                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7278                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7279                         break;
7280                 case 3 :
7281                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7282                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7283                         break;
7284                 case 4 :
7285                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7286                         break;
7287                 case 5 :
7288                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7289                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7290                         break;
7291                 case 6 :
7292                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7293                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7294                         break;
7295                 case 7 :
7296                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7297                         break;
7298         }
7299
7300         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7301 }
7302
7303 /*-----------------------------------------------------------------*/
7304 /* AccRsh - right shift accumulator by known count                 */
7305 /*-----------------------------------------------------------------*/
7306 static void AccRsh (int shCount, int andmask)
7307 {
7308         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7309         switch(shCount){
7310                 case 0 :
7311                         return; break;
7312                 case 1 :
7313                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7314 //                      andmask = 0;    /* no need */
7315                         break;
7316                 case 2 :
7317                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7318                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7319 //                      andmask = 0;    /* no need */
7320                         break;
7321                 case 3 :
7322                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7323                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7324                         break;
7325                 case 4 :
7326                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7327                         break;
7328                 case 5 :
7329                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7330                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7331                         break;
7332                 case 6 :
7333                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7334                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7335                         break;
7336                 case 7 :
7337                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7338                         break;
7339         }
7340         
7341         if(andmask)
7342                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7343         else
7344                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7345 }
7346
7347 #if 0
7348 /*-----------------------------------------------------------------*/
7349 /* AccSRsh - signed right shift accumulator by known count                 */
7350 /*-----------------------------------------------------------------*/
7351 static void AccSRsh (int shCount)
7352 {
7353     symbol *tlbl ;
7354     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7355     if(shCount != 0){
7356         if(shCount == 1){
7357             pic16_emitcode("mov","c,acc.7");
7358             pic16_emitcode("rrc","a");
7359         } else if(shCount == 2){
7360             pic16_emitcode("mov","c,acc.7");
7361             pic16_emitcode("rrc","a");
7362             pic16_emitcode("mov","c,acc.7");
7363             pic16_emitcode("rrc","a");
7364         } else {
7365             tlbl = newiTempLabel(NULL);
7366             /* rotate right accumulator */
7367             AccRol(8 - shCount);
7368             /* and kill the higher order bits */
7369             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7370             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7371             pic16_emitcode("orl","a,#0x%02x",
7372                      (unsigned char)~SRMask[shCount]);
7373             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7374         }
7375     }
7376 }
7377 #endif
7378 /*-----------------------------------------------------------------*/
7379 /* shiftR1Left2Result - shift right one byte from left to result   */
7380 /*-----------------------------------------------------------------*/
7381 static void shiftR1Left2ResultSigned (operand *left, int offl,
7382                                 operand *result, int offr,
7383                                 int shCount)
7384 {
7385   int same;
7386
7387   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7388
7389   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7390
7391   switch(shCount) {
7392   case 1:
7393     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7394     if(same) 
7395       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7396     else {
7397       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7398       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7399     }
7400
7401     break;
7402   case 2:
7403
7404     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7405     if(same) 
7406       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7407     else {
7408       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7409       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7410     }
7411     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7412     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7413
7414     break;
7415
7416   case 3:
7417     if(same)
7418       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7419     else {
7420       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7421       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7422     }
7423
7424     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7425     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7426     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7427
7428     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7429     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7430
7431     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7432     break;
7433
7434   case 4:
7435     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7436     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7437     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7438     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7439     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7440     break;
7441   case 5:
7442     if(same) {
7443       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7444     } else {
7445       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7446       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7447     }
7448     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7449     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7450     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7451     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7452     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7453     break;
7454
7455   case 6:
7456     if(same) {
7457       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7458       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7459       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7460       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7461       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7462       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7463     } else {
7464       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7465       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7466       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7467       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7468       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7469     }
7470     break;
7471
7472   case 7:
7473     if(same) {
7474       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7475       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7476       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7477       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7478     } else {
7479       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7480       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7481       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7482     }
7483
7484   default:
7485     break;
7486   }
7487 }
7488
7489 /*-----------------------------------------------------------------*/
7490 /* shiftR1Left2Result - shift right one byte from left to result   */
7491 /*-----------------------------------------------------------------*/
7492 static void shiftR1Left2Result (operand *left, int offl,
7493                                 operand *result, int offr,
7494                                 int shCount, int sign)
7495 {
7496   int same;
7497
7498   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7499
7500   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7501
7502   /* Copy the msb into the carry if signed. */
7503   if(sign) {
7504     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7505     return;
7506   }
7507
7508
7509
7510   switch(shCount) {
7511   case 1:
7512     emitCLRC;
7513     if(same) 
7514       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7515     else {
7516       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7517       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7518     }
7519     break;
7520   case 2:
7521     emitCLRC;
7522     if(same) {
7523       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7524     } else {
7525       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7526       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7527     }
7528     emitCLRC;
7529     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7530
7531     break;
7532   case 3:
7533     if(same)
7534       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7535     else {
7536       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7537       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7538     }
7539
7540     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7541     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7542     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7543     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7544     break;
7545       
7546   case 4:
7547     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7548     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7549     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7550     break;
7551
7552   case 5:
7553     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7554     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7555     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7556     emitCLRC;
7557     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7558
7559     break;
7560   case 6:
7561
7562     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7563     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7564     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7565     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7566     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7567     break;
7568
7569   case 7:
7570
7571     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7572     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7573     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7574
7575     break;
7576
7577   default:
7578     break;
7579   }
7580 }
7581
7582 /*-----------------------------------------------------------------*/
7583 /* shiftL1Left2Result - shift left one byte from left to result    */
7584 /*-----------------------------------------------------------------*/
7585 static void shiftL1Left2Result (operand *left, int offl,
7586                                 operand *result, int offr, int shCount)
7587 {
7588   int same;
7589
7590   //    char *l;
7591   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7592
7593   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7594   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7595     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7596     //    MOVA(l);
7597     /* shift left accumulator */
7598     //AccLsh(shCount); // don't comment out just yet...
7599   //    pic16_aopPut(AOP(result),"a",offr);
7600
7601   switch(shCount) {
7602   case 1:
7603     /* Shift left 1 bit position */
7604     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7605     if(same) {
7606       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7607     } else {
7608       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7609       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7610     }
7611     break;
7612   case 2:
7613     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7614     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7615     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7616     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7617     break;
7618   case 3:
7619     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7620     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7621     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7622     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7623     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7624     break;
7625   case 4:
7626     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7627     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7628     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7629     break;
7630   case 5:
7631     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7632     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7633     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7634     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7635     break;
7636   case 6:
7637     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7638     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7639     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7640     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7641     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7642     break;
7643   case 7:
7644     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7645     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7646     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7647     break;
7648
7649   default:
7650     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7651   }
7652
7653 }
7654
7655 /*-----------------------------------------------------------------*/
7656 /* movLeft2Result - move byte from left to result                  */
7657 /*-----------------------------------------------------------------*/
7658 static void movLeft2Result (operand *left, int offl,
7659                             operand *result, int offr)
7660 {
7661   char *l;
7662   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7663   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7664     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7665
7666     if (*l == '@' && (IS_AOP_PREG(result))) {
7667       pic16_emitcode("mov","a,%s",l);
7668       pic16_aopPut(AOP(result),"a",offr);
7669     } else {
7670       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7671       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7672     }
7673   }
7674 }
7675
7676 /*-----------------------------------------------------------------*/
7677 /* shiftL2Left2Result - shift left two bytes from left to result   */
7678 /*-----------------------------------------------------------------*/
7679 static void shiftL2Left2Result (operand *left, int offl,
7680                                 operand *result, int offr, int shCount)
7681 {
7682   int same = pic16_sameRegs(AOP(result), AOP(left));
7683   int i;
7684
7685   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7686
7687   if (same && (offl != offr)) { // shift bytes
7688     if (offr > offl) {
7689        for(i=1;i>-1;i--) {
7690          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7691          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7692        }
7693     } else { // just treat as different later on
7694                 same = 0;
7695     }
7696   }
7697
7698   if(same) {
7699     switch(shCount) {
7700     case 0:
7701       break;
7702     case 1:
7703     case 2:
7704     case 3:
7705
7706       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7707       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7708       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7709
7710       while(--shCount) {
7711                 emitCLRC;
7712                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7713                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7714       }
7715
7716       break;
7717     case 4:
7718     case 5:
7719       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7720       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7721       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7722       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7723       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7724       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7725       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7726       if(shCount >=5) {
7727                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7728                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7729       }
7730       break;
7731     case 6:
7732       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7733       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7734       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7735       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7736       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7737       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7738       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7739       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7740       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7741       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7742       break;
7743     case 7:
7744       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7745       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7746       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7747       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7748       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7749     }
7750
7751   } else {
7752     switch(shCount) {
7753     case 0:
7754       break;
7755     case 1:
7756     case 2:
7757     case 3:
7758       /* note, use a mov/add for the shift since the mov has a
7759          chance of getting optimized out */
7760       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7761       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7762       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7763       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7765
7766       while(--shCount) {
7767                 emitCLRC;
7768                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7769                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7770       }
7771       break;
7772
7773     case 4:
7774     case 5:
7775       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7776       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7777       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7778       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7779       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7780       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7781       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7782       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7783
7784
7785       if(shCount == 5) {
7786                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7787                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7788       }
7789       break;
7790     case 6:
7791       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7792       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7793       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7794       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7795
7796       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7797       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7798       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7799       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7800       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7801       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7802       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7803       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7804       break;
7805     case 7:
7806       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7807       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7808       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7809       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7810       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7811     }
7812   }
7813
7814 }
7815 /*-----------------------------------------------------------------*/
7816 /* shiftR2Left2Result - shift right two bytes from left to result  */
7817 /*-----------------------------------------------------------------*/
7818 static void shiftR2Left2Result (operand *left, int offl,
7819                                 operand *result, int offr,
7820                                 int shCount, int sign)
7821 {
7822   int same = pic16_sameRegs(AOP(result), AOP(left));
7823   int i;
7824   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7825
7826   if (same && (offl != offr)) { // shift right bytes
7827     if (offr < offl) {
7828        for(i=0;i<2;i++) {
7829          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7830          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7831        }
7832     } else { // just treat as different later on
7833                 same = 0;
7834     }
7835   }
7836
7837   switch(shCount) {
7838   case 0:
7839     break;
7840   case 1:
7841   case 2:
7842   case 3:
7843     if(sign)
7844       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7845     else
7846       emitCLRC;
7847
7848     if(same) {
7849       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7850       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7851     } else {
7852       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7853       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7854       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7855       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7856     }
7857
7858     while(--shCount) {
7859       if(sign)
7860                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7861       else
7862                 emitCLRC;
7863       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7864       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7865     }
7866     break;
7867   case 4:
7868   case 5:
7869     if(same) {
7870
7871       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7872       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7873       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7874
7875       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7876       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7877       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7878       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7879     } else {
7880       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7881       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7882       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7883
7884       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7885       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7886       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7887       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7888       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7889     }
7890
7891     if(shCount >=5) {
7892       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7893       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7894     }
7895
7896     if(sign) {
7897       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7898       pic16_emitpcode(POC_BTFSC, 
7899                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7900       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7901     }
7902
7903     break;
7904
7905   case 6:
7906     if(same) {
7907
7908       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7909       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7910
7911       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7912       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7913       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7914       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7915       if(sign) {
7916         pic16_emitpcode(POC_BTFSC, 
7917                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7918         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7919       }
7920       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7921       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7922       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7923       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7924     } else {
7925       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7926       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7927       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7928       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7929       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7930       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7931       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7932       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7933       if(sign) {
7934         pic16_emitpcode(POC_BTFSC, 
7935                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7936         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7937       }
7938       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7939       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7940
7941         
7942     }
7943
7944     break;
7945   case 7:
7946     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7947     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7948     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7949     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7950     if(sign) {
7951       emitSKPNC;
7952       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7953     } else 
7954       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7955   }
7956 }
7957
7958
7959 /*-----------------------------------------------------------------*/
7960 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7961 /*-----------------------------------------------------------------*/
7962 static void shiftLLeftOrResult (operand *left, int offl,
7963                                 operand *result, int offr, int shCount)
7964 {
7965     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7966
7967     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7968     /* shift left accumulator */
7969     AccLsh(shCount);
7970     /* or with result */
7971     /* back to result */
7972     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7973 }
7974
7975 /*-----------------------------------------------------------------*/
7976 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7977 /*-----------------------------------------------------------------*/
7978 static void shiftRLeftOrResult (operand *left, int offl,
7979                                 operand *result, int offr, int shCount)
7980 {
7981     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7982     
7983     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7984     /* shift right accumulator */
7985     AccRsh(shCount, 1);
7986     /* or with result */
7987     /* back to result */
7988     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* genlshOne - left shift a one byte quantity by known count       */
7993 /*-----------------------------------------------------------------*/
7994 static void genlshOne (operand *result, operand *left, int shCount)
7995 {       
7996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7997     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7998 }
7999
8000 /*-----------------------------------------------------------------*/
8001 /* genlshTwo - left shift two bytes by known amount != 0           */
8002 /*-----------------------------------------------------------------*/
8003 static void genlshTwo (operand *result,operand *left, int shCount)
8004 {
8005     int size;
8006     
8007     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8008     size = pic16_getDataSize(result);
8009
8010     /* if shCount >= 8 */
8011     if (shCount >= 8) {
8012         shCount -= 8 ;
8013
8014         if (size > 1){
8015             if (shCount)
8016                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8017             else 
8018                 movLeft2Result(left, LSB, result, MSB16);
8019         }
8020         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8021     }
8022
8023     /*  1 <= shCount <= 7 */
8024     else {  
8025         if(size == 1)
8026             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8027         else 
8028             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8029     }
8030 }
8031
8032 /*-----------------------------------------------------------------*/
8033 /* shiftLLong - shift left one long from left to result            */
8034 /* offr = LSB or MSB16                                             */
8035 /*-----------------------------------------------------------------*/
8036 static void shiftLLong (operand *left, operand *result, int offr )
8037 {
8038     int size = AOP_SIZE(result);
8039     int same = pic16_sameRegs(AOP(left),AOP(result));
8040         int i;
8041
8042     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8043
8044         if (same && (offr == MSB16)) { //shift one byte
8045                 for(i=size-1;i>=MSB16;i--) {
8046                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8047                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8048                 }
8049         } else {
8050                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8051         }
8052         
8053     if (size >= LSB+offr ){
8054                 if (same) {
8055                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8056                 } else {
8057                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8058                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8059                 }
8060          }
8061
8062     if(size >= MSB16+offr){
8063                 if (same) {
8064                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8065                 } else {
8066                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8067                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8068                 }
8069     }
8070
8071     if(size >= MSB24+offr){
8072                 if (same) {
8073                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8074                 } else {
8075                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8076                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8077                 }
8078     }
8079
8080     if(size > MSB32+offr){
8081                 if (same) {
8082                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8083                 } else {
8084                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8085                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8086                 }
8087     }
8088     if(offr != LSB)
8089                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8090
8091 }
8092
8093 /*-----------------------------------------------------------------*/
8094 /* genlshFour - shift four byte by a known amount != 0             */
8095 /*-----------------------------------------------------------------*/
8096 static void genlshFour (operand *result, operand *left, int shCount)
8097 {
8098     int size;
8099
8100     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8101     size = AOP_SIZE(result);
8102
8103     /* if shifting more that 3 bytes */
8104     if (shCount >= 24 ) {
8105         shCount -= 24;
8106         if (shCount)
8107             /* lowest order of left goes to the highest
8108             order of the destination */
8109             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8110         else
8111             movLeft2Result(left, LSB, result, MSB32);
8112
8113                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8114                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8115                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8116
8117         return;
8118     }
8119
8120     /* more than two bytes */
8121     else if ( shCount >= 16 ) {
8122         /* lower order two bytes goes to higher order two bytes */
8123         shCount -= 16;
8124         /* if some more remaining */
8125         if (shCount)
8126             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8127         else {
8128             movLeft2Result(left, MSB16, result, MSB32);
8129             movLeft2Result(left, LSB, result, MSB24);
8130         }
8131                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8132                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8133         return;
8134     }    
8135
8136     /* if more than 1 byte */
8137     else if ( shCount >= 8 ) {
8138         /* lower order three bytes goes to higher order  three bytes */
8139         shCount -= 8;
8140         if(size == 2){
8141             if(shCount)
8142                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8143             else
8144                 movLeft2Result(left, LSB, result, MSB16);
8145         }
8146         else{   /* size = 4 */
8147             if(shCount == 0){
8148                 movLeft2Result(left, MSB24, result, MSB32);
8149                 movLeft2Result(left, MSB16, result, MSB24);
8150                 movLeft2Result(left, LSB, result, MSB16);
8151                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8152             }
8153             else if(shCount == 1)
8154                 shiftLLong(left, result, MSB16);
8155             else{
8156                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8157                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8158                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8159                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8160             }
8161         }
8162     }
8163
8164     /* 1 <= shCount <= 7 */
8165     else if(shCount <= 3)
8166     { 
8167         shiftLLong(left, result, LSB);
8168         while(--shCount >= 1)
8169             shiftLLong(result, result, LSB);
8170     }
8171     /* 3 <= shCount <= 7, optimize */
8172     else{
8173         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8174         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8175         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8176     }
8177 }
8178
8179 /*-----------------------------------------------------------------*/
8180 /* genLeftShiftLiteral - left shifting by known count              */
8181 /*-----------------------------------------------------------------*/
8182 static void genLeftShiftLiteral (operand *left,
8183                                  operand *right,
8184                                  operand *result,
8185                                  iCode *ic)
8186 {    
8187     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8188     int size;
8189
8190     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8191     pic16_freeAsmop(right,NULL,ic,TRUE);
8192
8193     pic16_aopOp(left,ic,FALSE);
8194     pic16_aopOp(result,ic,FALSE);
8195
8196     size = getSize(operandType(result));
8197
8198 #if VIEW_SIZE
8199     pic16_emitcode("; shift left ","result %d, left %d",size,
8200              AOP_SIZE(left));
8201 #endif
8202
8203     /* I suppose that the left size >= result size */
8204     if(shCount == 0){
8205         while(size--){
8206             movLeft2Result(left, size, result, size);
8207         }
8208     }
8209
8210     else if(shCount >= (size * 8))
8211         while(size--)
8212             pic16_aopPut(AOP(result),zero,size);
8213     else{
8214         switch (size) {
8215             case 1:
8216                 genlshOne (result,left,shCount);
8217                 break;
8218
8219             case 2:
8220             case 3:
8221                 genlshTwo (result,left,shCount);
8222                 break;
8223
8224             case 4:
8225                 genlshFour (result,left,shCount);
8226                 break;
8227         }
8228     }
8229     pic16_freeAsmop(left,NULL,ic,TRUE);
8230     pic16_freeAsmop(result,NULL,ic,TRUE);
8231 }
8232
8233 /*-----------------------------------------------------------------*
8234  * genMultiAsm - repeat assembly instruction for size of register.
8235  * if endian == 1, then the high byte (i.e base address + size of 
8236  * register) is used first else the low byte is used first;
8237  *-----------------------------------------------------------------*/
8238 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8239 {
8240
8241   int offset = 0;
8242
8243   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8244
8245   if(!reg)
8246     return;
8247
8248   if(!endian) {
8249     endian = 1;
8250   } else {
8251     endian = -1;
8252     offset = size-1;
8253   }
8254
8255   while(size--) {
8256     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8257     offset += endian;
8258   }
8259
8260 }
8261 /*-----------------------------------------------------------------*/
8262 /* genLeftShift - generates code for left shifting                 */
8263 /*-----------------------------------------------------------------*/
8264 static void genLeftShift (iCode *ic)
8265 {
8266   operand *left,*right, *result;
8267   int size, offset;
8268   char *l;
8269   symbol *tlbl , *tlbl1;
8270   pCodeOp *pctemp;
8271
8272   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8273
8274   right = IC_RIGHT(ic);
8275   left  = IC_LEFT(ic);
8276   result = IC_RESULT(ic);
8277
8278   pic16_aopOp(right,ic,FALSE);
8279
8280   /* if the shift count is known then do it 
8281      as efficiently as possible */
8282   if (AOP_TYPE(right) == AOP_LIT) {
8283     genLeftShiftLiteral (left,right,result,ic);
8284     return ;
8285   }
8286
8287   /* shift count is unknown then we have to form 
8288      a loop get the loop count in B : Note: we take
8289      only the lower order byte since shifting
8290      more that 32 bits make no sense anyway, ( the
8291      largest size of an object can be only 32 bits ) */  
8292
8293     
8294   pic16_aopOp(left,ic,FALSE);
8295   pic16_aopOp(result,ic,FALSE);
8296
8297   /* now move the left to the result if they are not the
8298      same */
8299   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8300       AOP_SIZE(result) > 1) {
8301
8302     size = AOP_SIZE(result);
8303     offset=0;
8304     while (size--) {
8305       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8306       if (*l == '@' && (IS_AOP_PREG(result))) {
8307
8308         pic16_emitcode("mov","a,%s",l);
8309         pic16_aopPut(AOP(result),"a",offset);
8310       } else {
8311         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8312         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8313         //pic16_aopPut(AOP(result),l,offset);
8314       }
8315       offset++;
8316     }
8317   }
8318
8319   size = AOP_SIZE(result);
8320
8321   /* if it is only one byte then */
8322   if (size == 1) {
8323     if(optimized_for_speed) {
8324       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8325       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8326       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8327       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8328       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8329       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8330       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8331       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8332       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8333       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8334       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8335       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8336     } else {
8337
8338       tlbl = newiTempLabel(NULL);
8339       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8340                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8341                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8342       }
8343
8344       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8345       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8346       pic16_emitpLabel(tlbl->key);
8347       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8348       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8349       emitSKPC;
8350       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8351     }
8352     goto release ;
8353   }
8354     
8355   if (pic16_sameRegs(AOP(left),AOP(result))) {
8356
8357     tlbl = newiTempLabel(NULL);
8358     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8359     genMultiAsm(POC_RRCF, result, size,1);
8360     pic16_emitpLabel(tlbl->key);
8361     genMultiAsm(POC_RLCF, result, size,0);
8362     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8363     emitSKPC;
8364     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8365     goto release;
8366   }
8367
8368   //tlbl = newiTempLabel(NULL);
8369   //offset = 0 ;   
8370   //tlbl1 = newiTempLabel(NULL);
8371
8372   //reAdjustPreg(AOP(result));    
8373     
8374   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8375   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8376   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8377   //MOVA(l);
8378   //pic16_emitcode("add","a,acc");         
8379   //pic16_aopPut(AOP(result),"a",offset++);
8380   //while (--size) {
8381   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8382   //  MOVA(l);
8383   //  pic16_emitcode("rlc","a");         
8384   //  pic16_aopPut(AOP(result),"a",offset++);
8385   //}
8386   //reAdjustPreg(AOP(result));
8387
8388   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8389   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8390
8391
8392   tlbl = newiTempLabel(NULL);
8393   tlbl1= newiTempLabel(NULL);
8394
8395   size = AOP_SIZE(result);
8396   offset = 1;
8397
8398   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8399
8400   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8401
8402   /* offset should be 0, 1 or 3 */
8403   
8404   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8405   emitSKPNZ;
8406   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8407
8408   pic16_emitpcode(POC_MOVWF, pctemp);
8409
8410
8411   pic16_emitpLabel(tlbl->key);
8412
8413   emitCLRC;
8414   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8415   while(--size)
8416     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8417
8418   pic16_emitpcode(POC_DECFSZ,  pctemp);
8419   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8420   pic16_emitpLabel(tlbl1->key);
8421
8422   pic16_popReleaseTempReg(pctemp);
8423
8424
8425  release:
8426   pic16_freeAsmop (right,NULL,ic,TRUE);
8427   pic16_freeAsmop(left,NULL,ic,TRUE);
8428   pic16_freeAsmop(result,NULL,ic,TRUE);
8429 }
8430
8431 /*-----------------------------------------------------------------*/
8432 /* genrshOne - right shift a one byte quantity by known count      */
8433 /*-----------------------------------------------------------------*/
8434 static void genrshOne (operand *result, operand *left,
8435                        int shCount, int sign)
8436 {
8437     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8438     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8439 }
8440
8441 /*-----------------------------------------------------------------*/
8442 /* genrshTwo - right shift two bytes by known amount != 0          */
8443 /*-----------------------------------------------------------------*/
8444 static void genrshTwo (operand *result,operand *left,
8445                        int shCount, int sign)
8446 {
8447   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8448   /* if shCount >= 8 */
8449   if (shCount >= 8) {
8450     shCount -= 8 ;
8451     if (shCount)
8452       shiftR1Left2Result(left, MSB16, result, LSB,
8453                          shCount, sign);
8454     else
8455       movLeft2Result(left, MSB16, result, LSB);
8456
8457     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8458
8459     if(sign) {
8460       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8461       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8462     }
8463   }
8464
8465   /*  1 <= shCount <= 7 */
8466   else
8467     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8468 }
8469
8470 /*-----------------------------------------------------------------*/
8471 /* shiftRLong - shift right one long from left to result           */
8472 /* offl = LSB or MSB16                                             */
8473 /*-----------------------------------------------------------------*/
8474 static void shiftRLong (operand *left, int offl,
8475                         operand *result, int sign)
8476 {
8477     int size = AOP_SIZE(result);
8478     int same = pic16_sameRegs(AOP(left),AOP(result));
8479     int i;
8480     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8481
8482         if (same && (offl == MSB16)) { //shift one byte right
8483                 for(i=MSB16;i<size;i++) {
8484                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8485                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8486                 }
8487         }
8488
8489     if(sign)
8490                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8491         else
8492                 emitCLRC;
8493
8494         if (same) {
8495                 if (offl == LSB)
8496                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8497         } else {
8498         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8499         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8500         }
8501
8502     if(offl == MSB16) {
8503         /* add sign of "a" */
8504         pic16_addSign(result, MSB32, sign);
8505         }
8506
8507         if (same) {
8508         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8509         } else {
8510         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8511         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8512         }
8513         
8514         if (same) {
8515         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8516         } else {
8517         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8518         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8519         }
8520
8521         if (same) {
8522         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8523         } else {
8524         if(offl == LSB){
8525                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8526                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8527         }
8528         }
8529 }
8530
8531 /*-----------------------------------------------------------------*/
8532 /* genrshFour - shift four byte by a known amount != 0             */
8533 /*-----------------------------------------------------------------*/
8534 static void genrshFour (operand *result, operand *left,
8535                         int shCount, int sign)
8536 {
8537   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8538   /* if shifting more that 3 bytes */
8539   if(shCount >= 24 ) {
8540     shCount -= 24;
8541     if(shCount)
8542       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8543     else
8544       movLeft2Result(left, MSB32, result, LSB);
8545
8546     pic16_addSign(result, MSB16, sign);
8547   }
8548   else if(shCount >= 16){
8549     shCount -= 16;
8550     if(shCount)
8551       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8552     else{
8553       movLeft2Result(left, MSB24, result, LSB);
8554       movLeft2Result(left, MSB32, result, MSB16);
8555     }
8556     pic16_addSign(result, MSB24, sign);
8557   }
8558   else if(shCount >= 8){
8559     shCount -= 8;
8560     if(shCount == 1)
8561       shiftRLong(left, MSB16, result, sign);
8562     else if(shCount == 0){
8563       movLeft2Result(left, MSB16, result, LSB);
8564       movLeft2Result(left, MSB24, result, MSB16);
8565       movLeft2Result(left, MSB32, result, MSB24);
8566       pic16_addSign(result, MSB32, sign);
8567     }
8568     else{ //shcount >= 2
8569       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8570       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8571       /* the last shift is signed */
8572       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8573       pic16_addSign(result, MSB32, sign);
8574     }
8575   }
8576   else{   /* 1 <= shCount <= 7 */
8577     if(shCount <= 2){
8578       shiftRLong(left, LSB, result, sign);
8579       if(shCount == 2)
8580         shiftRLong(result, LSB, result, sign);
8581     }
8582     else{
8583       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8584       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8585       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8586     }
8587   }
8588 }
8589
8590 /*-----------------------------------------------------------------*/
8591 /* genRightShiftLiteral - right shifting by known count            */
8592 /*-----------------------------------------------------------------*/
8593 static void genRightShiftLiteral (operand *left,
8594                                   operand *right,
8595                                   operand *result,
8596                                   iCode *ic,
8597                                   int sign)
8598 {    
8599   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8600   int lsize,res_size;
8601
8602   pic16_freeAsmop(right,NULL,ic,TRUE);
8603
8604   pic16_aopOp(left,ic,FALSE);
8605   pic16_aopOp(result,ic,FALSE);
8606
8607   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8608
8609 #if VIEW_SIZE
8610   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8611                  AOP_SIZE(left));
8612 #endif
8613
8614   lsize = pic16_getDataSize(left);
8615   res_size = pic16_getDataSize(result);
8616   /* test the LEFT size !!! */
8617
8618   /* I suppose that the left size >= result size */
8619   if(shCount == 0){
8620     while(res_size--)
8621       movLeft2Result(left, lsize, result, res_size);
8622   }
8623
8624   else if(shCount >= (lsize * 8)){
8625
8626     if(res_size == 1) {
8627       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8628       if(sign) {
8629         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8630         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8631       }
8632     } else {
8633
8634       if(sign) {
8635         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8636         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8637         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8638         while(res_size--)
8639           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8640
8641       } else {
8642
8643         while(res_size--)
8644           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8645       }
8646     }
8647   } else {
8648
8649     switch (res_size) {
8650     case 1:
8651       genrshOne (result,left,shCount,sign);
8652       break;
8653
8654     case 2:
8655       genrshTwo (result,left,shCount,sign);
8656       break;
8657
8658     case 4:
8659       genrshFour (result,left,shCount,sign);
8660       break;
8661     default :
8662       break;
8663     }
8664
8665   }
8666
8667   pic16_freeAsmop(left,NULL,ic,TRUE);
8668   pic16_freeAsmop(result,NULL,ic,TRUE);
8669 }
8670
8671 /*-----------------------------------------------------------------*/
8672 /* genSignedRightShift - right shift of signed number              */
8673 /*-----------------------------------------------------------------*/
8674 static void genSignedRightShift (iCode *ic)
8675 {
8676   operand *right, *left, *result;
8677   int size, offset;
8678   //  char *l;
8679   symbol *tlbl, *tlbl1 ;
8680   pCodeOp *pctemp;
8681
8682   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8683
8684   /* we do it the hard way put the shift count in b
8685      and loop thru preserving the sign */
8686   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8687
8688   right = IC_RIGHT(ic);
8689   left  = IC_LEFT(ic);
8690   result = IC_RESULT(ic);
8691
8692   pic16_aopOp(right,ic,FALSE);  
8693   pic16_aopOp(left,ic,FALSE);
8694   pic16_aopOp(result,ic,FALSE);
8695
8696
8697   if ( AOP_TYPE(right) == AOP_LIT) {
8698     genRightShiftLiteral (left,right,result,ic,1);
8699     return ;
8700   }
8701   /* shift count is unknown then we have to form 
8702      a loop get the loop count in B : Note: we take
8703      only the lower order byte since shifting
8704      more that 32 bits make no sense anyway, ( the
8705      largest size of an object can be only 32 bits ) */  
8706
8707   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8708   //pic16_emitcode("inc","b");
8709   //pic16_freeAsmop (right,NULL,ic,TRUE);
8710   //pic16_aopOp(left,ic,FALSE);
8711   //pic16_aopOp(result,ic,FALSE);
8712
8713   /* now move the left to the result if they are not the
8714      same */
8715   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8716       AOP_SIZE(result) > 1) {
8717
8718     size = AOP_SIZE(result);
8719     offset=0;
8720     while (size--) { 
8721       /*
8722         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8723         if (*l == '@' && IS_AOP_PREG(result)) {
8724
8725         pic16_emitcode("mov","a,%s",l);
8726         pic16_aopPut(AOP(result),"a",offset);
8727         } else
8728         pic16_aopPut(AOP(result),l,offset);
8729       */
8730       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8731       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8732
8733       offset++;
8734     }
8735   }
8736
8737   /* mov the highest order bit to OVR */    
8738   tlbl = newiTempLabel(NULL);
8739   tlbl1= newiTempLabel(NULL);
8740
8741   size = AOP_SIZE(result);
8742   offset = size - 1;
8743
8744   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8745
8746   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8747
8748   /* offset should be 0, 1 or 3 */
8749   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8750   emitSKPNZ;
8751   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8752
8753   pic16_emitpcode(POC_MOVWF, pctemp);
8754
8755
8756   pic16_emitpLabel(tlbl->key);
8757
8758   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8759   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8760
8761   while(--size) {
8762     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8763   }
8764
8765   pic16_emitpcode(POC_DECFSZ,  pctemp);
8766   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8767   pic16_emitpLabel(tlbl1->key);
8768
8769   pic16_popReleaseTempReg(pctemp);
8770 #if 0
8771   size = AOP_SIZE(result);
8772   offset = size - 1;
8773   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8774   pic16_emitcode("rlc","a");
8775   pic16_emitcode("mov","ov,c");
8776   /* if it is only one byte then */
8777   if (size == 1) {
8778     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8779     MOVA(l);
8780     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8781     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8782     pic16_emitcode("mov","c,ov");
8783     pic16_emitcode("rrc","a");
8784     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8785     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8786     pic16_aopPut(AOP(result),"a",0);
8787     goto release ;
8788   }
8789
8790   reAdjustPreg(AOP(result));
8791   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8792   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8793   pic16_emitcode("mov","c,ov");
8794   while (size--) {
8795     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8796     MOVA(l);
8797     pic16_emitcode("rrc","a");         
8798     pic16_aopPut(AOP(result),"a",offset--);
8799   }
8800   reAdjustPreg(AOP(result));
8801   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8802   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8803
8804  release:
8805 #endif
8806
8807   pic16_freeAsmop(left,NULL,ic,TRUE);
8808   pic16_freeAsmop(result,NULL,ic,TRUE);
8809   pic16_freeAsmop(right,NULL,ic,TRUE);
8810 }
8811
8812 /*-----------------------------------------------------------------*/
8813 /* genRightShift - generate code for right shifting                */
8814 /*-----------------------------------------------------------------*/
8815 static void genRightShift (iCode *ic)
8816 {
8817     operand *right, *left, *result;
8818     sym_link *letype ;
8819     int size, offset;
8820     char *l;
8821     symbol *tlbl, *tlbl1 ;
8822
8823     /* if signed then we do it the hard way preserve the
8824     sign bit moving it inwards */
8825     letype = getSpec(operandType(IC_LEFT(ic)));
8826     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8827
8828     if (!SPEC_USIGN(letype)) {
8829         genSignedRightShift (ic);
8830         return ;
8831     }
8832
8833     /* signed & unsigned types are treated the same : i.e. the
8834     signed is NOT propagated inwards : quoting from the
8835     ANSI - standard : "for E1 >> E2, is equivalent to division
8836     by 2**E2 if unsigned or if it has a non-negative value,
8837     otherwise the result is implementation defined ", MY definition
8838     is that the sign does not get propagated */
8839
8840     right = IC_RIGHT(ic);
8841     left  = IC_LEFT(ic);
8842     result = IC_RESULT(ic);
8843
8844     pic16_aopOp(right,ic,FALSE);
8845
8846     /* if the shift count is known then do it 
8847     as efficiently as possible */
8848     if (AOP_TYPE(right) == AOP_LIT) {
8849         genRightShiftLiteral (left,right,result,ic, 0);
8850         return ;
8851     }
8852
8853     /* shift count is unknown then we have to form 
8854     a loop get the loop count in B : Note: we take
8855     only the lower order byte since shifting
8856     more that 32 bits make no sense anyway, ( the
8857     largest size of an object can be only 32 bits ) */  
8858
8859     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8860     pic16_emitcode("inc","b");
8861     pic16_aopOp(left,ic,FALSE);
8862     pic16_aopOp(result,ic,FALSE);
8863
8864     /* now move the left to the result if they are not the
8865     same */
8866     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8867         AOP_SIZE(result) > 1) {
8868
8869         size = AOP_SIZE(result);
8870         offset=0;
8871         while (size--) {
8872             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8873             if (*l == '@' && IS_AOP_PREG(result)) {
8874
8875                 pic16_emitcode("mov","a,%s",l);
8876                 pic16_aopPut(AOP(result),"a",offset);
8877             } else
8878                 pic16_aopPut(AOP(result),l,offset);
8879             offset++;
8880         }
8881     }
8882
8883     tlbl = newiTempLabel(NULL);
8884     tlbl1= newiTempLabel(NULL);
8885     size = AOP_SIZE(result);
8886     offset = size - 1;
8887
8888     /* if it is only one byte then */
8889     if (size == 1) {
8890
8891       tlbl = newiTempLabel(NULL);
8892       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8893         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8894         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8895       }
8896
8897       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8898       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8899       pic16_emitpLabel(tlbl->key);
8900       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8901       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8902       emitSKPC;
8903       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8904
8905       goto release ;
8906     }
8907
8908     reAdjustPreg(AOP(result));
8909     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8910     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8911     CLRC;
8912     while (size--) {
8913         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8914         MOVA(l);
8915         pic16_emitcode("rrc","a");         
8916         pic16_aopPut(AOP(result),"a",offset--);
8917     }
8918     reAdjustPreg(AOP(result));
8919
8920     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8921     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8922
8923 release:
8924     pic16_freeAsmop(left,NULL,ic,TRUE);
8925     pic16_freeAsmop (right,NULL,ic,TRUE);
8926     pic16_freeAsmop(result,NULL,ic,TRUE);
8927 }
8928
8929 /*-----------------------------------------------------------------*/
8930 /* genUnpackBits - generates code for unpacking bits               */
8931 /*-----------------------------------------------------------------*/
8932 static void genUnpackBits (operand *result, char *rname, int ptype)
8933 {    
8934     int shCnt ;
8935     int rlen = 0 ;
8936     sym_link *etype;
8937     int offset = 0 ;
8938
8939         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8940         etype = getSpec(operandType(result));
8941
8942         /* read the first byte  */
8943         switch (ptype) {
8944                 case POINTER:
8945                 case IPOINTER:
8946                 case PPOINTER:
8947                 case FPOINTER:
8948                 case GPOINTER:
8949                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8950                         break;
8951                 case CPOINTER:
8952                         pic16_emitcode("clr","a");
8953                         pic16_emitcode("movc","a","@a+dptr");
8954                         break;
8955         }
8956         
8957
8958         /* if we have bitdisplacement then it fits   */
8959         /* into this byte completely or if length is */
8960         /* less than a byte                          */
8961         if ((shCnt = SPEC_BSTR(etype)) || 
8962                 (SPEC_BLEN(etype) <= 8))  {
8963
8964                 /* shift right acc */
8965                 AccRsh(shCnt, 0);
8966
8967                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8968                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8969
8970 /* VR -- normally I would use the following, but since we use the hack,
8971  * to avoid the masking from AccRsh, why not mask it right now? */
8972
8973 /*
8974                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8975 */
8976
8977                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8978           return ;
8979         }
8980
8981
8982
8983         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8984         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8985         exit(-1);
8986
8987     /* bit field did not fit in a byte  */
8988     rlen = SPEC_BLEN(etype) - 8;
8989     pic16_aopPut(AOP(result),"a",offset++);
8990
8991     while (1)  {
8992
8993         switch (ptype) {
8994         case POINTER:
8995         case IPOINTER:
8996             pic16_emitcode("inc","%s",rname);
8997             pic16_emitcode("mov","a,@%s",rname);
8998             break;
8999             
9000         case PPOINTER:
9001             pic16_emitcode("inc","%s",rname);
9002             pic16_emitcode("movx","a,@%s",rname);
9003             break;
9004
9005         case FPOINTER:
9006             pic16_emitcode("inc","dptr");
9007             pic16_emitcode("movx","a,@dptr");
9008             break;
9009             
9010         case CPOINTER:
9011             pic16_emitcode("clr","a");
9012             pic16_emitcode("inc","dptr");
9013             pic16_emitcode("movc","a","@a+dptr");
9014             break;
9015             
9016         case GPOINTER:
9017             pic16_emitcode("inc","dptr");
9018             pic16_emitcode("lcall","__gptrget");
9019             break;
9020         }
9021
9022         rlen -= 8;            
9023         /* if we are done */
9024         if ( rlen <= 0 )
9025             break ;
9026         
9027         pic16_aopPut(AOP(result),"a",offset++);
9028                               
9029     }
9030     
9031     if (rlen) {
9032         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9033         pic16_aopPut(AOP(result),"a",offset);          
9034     }
9035     
9036     return ;
9037 }
9038
9039
9040 static void genDataPointerGet(operand *left,
9041                               operand *result,
9042                               iCode *ic)
9043 {
9044   int size, offset = 0, leoffset=0 ;
9045
9046         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9047         pic16_aopOp(result, ic, FALSE);
9048
9049         size = AOP_SIZE(result);
9050 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9051
9052
9053 #if 0
9054         /* The following tests may save a redudant movff instruction when
9055          * accessing unions */
9056          
9057         /* if they are the same */
9058         if (operandsEqu (left, result)) {
9059                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9060                 goto release;
9061         }
9062 #endif
9063
9064 #if 0
9065         /* if they are the same registers */
9066         if (pic16_sameRegs(AOP(left),AOP(result))) {
9067                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9068                 goto release;
9069         }
9070 #endif
9071
9072 #if 0
9073         if ( AOP_TYPE(left) == AOP_PCODE) {
9074                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9075                                 AOP(left)->aopu.pcop->name,
9076                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9077                                 PCOR(AOP(left)->aopu.pcop)->instance:
9078                                 PCOI(AOP(left)->aopu.pcop)->offset);
9079         }
9080 #endif
9081
9082         if(AOP(left)->aopu.pcop->type == PO_DIR)
9083                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9084
9085         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9086
9087         while (size--) {
9088                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9089                 
9090                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9091                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9092                         mov2w(AOP(left), offset); // patch 8
9093                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9094                 } else {
9095                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9096                                 pic16_popGet(AOP(left), offset), //patch 8
9097                                 pic16_popGet(AOP(result), offset)));
9098                 }
9099
9100                 offset++;
9101                 leoffset++;
9102         }
9103
9104 //release:
9105     pic16_freeAsmop(result,NULL,ic,TRUE);
9106 }
9107
9108 void pic16_loadFSR0(operand *op)
9109 {
9110         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9111 }
9112
9113
9114 /*-----------------------------------------------------------------*/
9115 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9116 /*-----------------------------------------------------------------*/
9117 static void genNearPointerGet (operand *left, 
9118                                operand *result, 
9119                                iCode *ic)
9120 {
9121     asmop *aop = NULL;
9122     //regs *preg = NULL ;
9123     sym_link *rtype, *retype;
9124     sym_link *ltype = operandType(left);    
9125
9126         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9127         rtype = operandType(result);
9128         retype= getSpec(rtype);
9129     
9130         pic16_aopOp(left,ic,FALSE);
9131
9132         pic16_DumpOp("(left)",left);
9133         pic16_DumpOp("(result)",result);
9134
9135         /* if left is rematerialisable and
9136          * result is not bit variable type and
9137          * the left is pointer to data space i.e
9138          * lower 128 bytes of space */
9139         if (AOP_TYPE(left) == AOP_PCODE
9140                 && !IS_BITFIELD(retype)
9141                 && DCL_TYPE(ltype) == POINTER) {
9142
9143                 genDataPointerGet (left,result,ic);
9144                 pic16_freeAsmop(left, NULL, ic, TRUE);
9145           return ;
9146         }
9147     
9148         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9149
9150         /* if the value is already in a pointer register
9151          * then don't need anything more */
9152         if (!AOP_INPREG(AOP(left))) {
9153                 /* otherwise get a free pointer register */
9154                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9155                 
9156                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9157                 if( (AOP_TYPE(left) == AOP_PCODE) 
9158                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9159                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9160                 {
9161                         pic16_loadFSR0( left );  // patch 10
9162                 } else {
9163                         // set up FSR0 with address from left
9164                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9165                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9166                 }
9167         }
9168 //       else
9169 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9170     
9171         pic16_aopOp (result,ic,FALSE);
9172     
9173       /* if bitfield then unpack the bits */
9174     if (IS_BITFIELD(retype)) 
9175         genUnpackBits (result, NULL, POINTER);
9176     else {
9177         /* we have can just get the values */
9178       int size = AOP_SIZE(result);
9179       int offset = 0;   
9180         
9181       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9182
9183
9184         /* fsr0 is loaded already -- VR */
9185 //      pic16_loadFSR0( left );
9186
9187 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9188 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9189       while(size--) {
9190
9191         if(size) {
9192                 pic16_emitpcode(POC_MOVFF,
9193                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9194                                 pic16_popGet(AOP(result), offset++)));
9195         } else {
9196                 pic16_emitpcode(POC_MOVFF,
9197                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9198                                 pic16_popGet(AOP(result), offset++)));
9199         }
9200       }
9201 #if 0
9202 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9203 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9204         if(size)
9205           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9206 #endif
9207 /*
9208         while (size--) {
9209             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9210
9211                 pic16_emitcode("mov","a,@%s",rname);
9212                 pic16_aopPut(AOP(result),"a",offset);
9213             } else {
9214                 sprintf(buffer,"@%s",rname);
9215                 pic16_aopPut(AOP(result),buffer,offset);
9216             }
9217             offset++ ;
9218             if (size)
9219                 pic16_emitcode("inc","%s",rname);
9220         }
9221 */
9222     }
9223
9224     /* now some housekeeping stuff */
9225     if (aop) {
9226         /* we had to allocate for this iCode */
9227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9228         pic16_freeAsmop(NULL,aop,ic,TRUE);
9229     } else { 
9230         /* we did not allocate which means left
9231            already in a pointer register, then
9232            if size > 0 && this could be used again
9233            we have to point it back to where it 
9234            belongs */
9235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9236         if (AOP_SIZE(result) > 1 &&
9237             !OP_SYMBOL(left)->remat &&
9238             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9239               ic->depth )) {
9240 //          int size = AOP_SIZE(result) - 1;
9241 //          while (size--)
9242 //              pic16_emitcode("dec","%s",rname);
9243         }
9244     }
9245
9246     /* done */
9247     pic16_freeAsmop(left,NULL,ic,TRUE);
9248     pic16_freeAsmop(result,NULL,ic,TRUE);
9249      
9250 }
9251
9252 /*-----------------------------------------------------------------*/
9253 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9254 /*-----------------------------------------------------------------*/
9255 static void genPagedPointerGet (operand *left, 
9256                                operand *result, 
9257                                iCode *ic)
9258 {
9259     asmop *aop = NULL;
9260     regs *preg = NULL ;
9261     char *rname ;
9262     sym_link *rtype, *retype;    
9263
9264     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9265
9266     rtype = operandType(result);
9267     retype= getSpec(rtype);
9268     
9269     pic16_aopOp(left,ic,FALSE);
9270
9271   /* if the value is already in a pointer register
9272        then don't need anything more */
9273     if (!AOP_INPREG(AOP(left))) {
9274         /* otherwise get a free pointer register */
9275         aop = newAsmop(0);
9276         preg = getFreePtr(ic,&aop,FALSE);
9277         pic16_emitcode("mov","%s,%s",
9278                 preg->name,
9279                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9280         rname = preg->name ;
9281     } else
9282         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9283     
9284     pic16_freeAsmop(left,NULL,ic,TRUE);
9285     pic16_aopOp (result,ic,FALSE);
9286
9287     /* if bitfield then unpack the bits */
9288     if (IS_BITFIELD(retype)) 
9289         genUnpackBits (result,rname,PPOINTER);
9290     else {
9291         /* we have can just get the values */
9292         int size = AOP_SIZE(result);
9293         int offset = 0 ;        
9294         
9295         while (size--) {
9296             
9297             pic16_emitcode("movx","a,@%s",rname);
9298             pic16_aopPut(AOP(result),"a",offset);
9299             
9300             offset++ ;
9301             
9302             if (size)
9303                 pic16_emitcode("inc","%s",rname);
9304         }
9305     }
9306
9307     /* now some housekeeping stuff */
9308     if (aop) {
9309         /* we had to allocate for this iCode */
9310         pic16_freeAsmop(NULL,aop,ic,TRUE);
9311     } else { 
9312         /* we did not allocate which means left
9313            already in a pointer register, then
9314            if size > 0 && this could be used again
9315            we have to point it back to where it 
9316            belongs */
9317         if (AOP_SIZE(result) > 1 &&
9318             !OP_SYMBOL(left)->remat &&
9319             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9320               ic->depth )) {
9321             int size = AOP_SIZE(result) - 1;
9322             while (size--)
9323                 pic16_emitcode("dec","%s",rname);
9324         }
9325     }
9326
9327     /* done */
9328     pic16_freeAsmop(result,NULL,ic,TRUE);
9329     
9330         
9331 }
9332
9333 /*-----------------------------------------------------------------*/
9334 /* genFarPointerGet - gget value from far space                    */
9335 /*-----------------------------------------------------------------*/
9336 static void genFarPointerGet (operand *left,
9337                               operand *result, iCode *ic)
9338 {
9339     int size, offset ;
9340     sym_link *retype = getSpec(operandType(result));
9341
9342     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9343
9344     pic16_aopOp(left,ic,FALSE);
9345
9346     /* if the operand is already in dptr 
9347     then we do nothing else we move the value to dptr */
9348     if (AOP_TYPE(left) != AOP_STR) {
9349         /* if this is remateriazable */
9350         if (AOP_TYPE(left) == AOP_IMMD)
9351             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9352         else { /* we need to get it byte by byte */
9353             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9354             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9355             if (options.model == MODEL_FLAT24)
9356             {
9357                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9358             }
9359         }
9360     }
9361     /* so dptr know contains the address */
9362     pic16_freeAsmop(left,NULL,ic,TRUE);
9363     pic16_aopOp(result,ic,FALSE);
9364
9365     /* if bit then unpack */
9366     if (IS_BITFIELD(retype)) 
9367         genUnpackBits(result,"dptr",FPOINTER);
9368     else {
9369         size = AOP_SIZE(result);
9370         offset = 0 ;
9371
9372         while (size--) {
9373             pic16_emitcode("movx","a,@dptr");
9374             pic16_aopPut(AOP(result),"a",offset++);
9375             if (size)
9376                 pic16_emitcode("inc","dptr");
9377         }
9378     }
9379
9380     pic16_freeAsmop(result,NULL,ic,TRUE);
9381 }
9382 #if 0
9383 /*-----------------------------------------------------------------*/
9384 /* genCodePointerGet - get value from code space                  */
9385 /*-----------------------------------------------------------------*/
9386 static void genCodePointerGet (operand *left,
9387                                 operand *result, iCode *ic)
9388 {
9389     int size, offset ;
9390     sym_link *retype = getSpec(operandType(result));
9391
9392     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9393
9394     pic16_aopOp(left,ic,FALSE);
9395
9396     /* if the operand is already in dptr 
9397     then we do nothing else we move the value to dptr */
9398     if (AOP_TYPE(left) != AOP_STR) {
9399         /* if this is remateriazable */
9400         if (AOP_TYPE(left) == AOP_IMMD)
9401             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9402         else { /* we need to get it byte by byte */
9403             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9404             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9405             if (options.model == MODEL_FLAT24)
9406             {
9407                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9408             }
9409         }
9410     }
9411     /* so dptr know contains the address */
9412     pic16_freeAsmop(left,NULL,ic,TRUE);
9413     pic16_aopOp(result,ic,FALSE);
9414
9415     /* if bit then unpack */
9416     if (IS_BITFIELD(retype)) 
9417         genUnpackBits(result,"dptr",CPOINTER);
9418     else {
9419         size = AOP_SIZE(result);
9420         offset = 0 ;
9421
9422         while (size--) {
9423             pic16_emitcode("clr","a");
9424             pic16_emitcode("movc","a,@a+dptr");
9425             pic16_aopPut(AOP(result),"a",offset++);
9426             if (size)
9427                 pic16_emitcode("inc","dptr");
9428         }
9429     }
9430
9431     pic16_freeAsmop(result,NULL,ic,TRUE);
9432 }
9433 #endif
9434 /*-----------------------------------------------------------------*/
9435 /* genGenPointerGet - gget value from generic pointer space        */
9436 /*-----------------------------------------------------------------*/
9437 static void genGenPointerGet (operand *left,
9438                               operand *result, iCode *ic)
9439 {
9440   int size, offset, lit;
9441   sym_link *retype = getSpec(operandType(result));
9442
9443         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9444         pic16_aopOp(left,ic,FALSE);
9445         pic16_aopOp(result,ic,FALSE);
9446         size = AOP_SIZE(result);
9447
9448         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9449
9450         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9451
9452                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9453                 // load FSR0 from immediate
9454                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9455
9456 //              pic16_loadFSR0( left );
9457
9458                 offset = 0;
9459                 while(size--) {
9460                         if(size) {
9461                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9462                         } else {
9463                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9464                         }
9465                         offset++;
9466                 }
9467                 goto release;
9468
9469         }
9470         else { /* we need to get it byte by byte */
9471                 // set up FSR0 with address from left
9472                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9473                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9474
9475                 offset = 0 ;
9476
9477                 while(size--) {
9478                         if(size) {
9479                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9480                         } else {
9481                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9482                         }
9483                         offset++;
9484                 }
9485                 goto release;
9486         }
9487
9488   /* if bit then unpack */
9489         if (IS_BITFIELD(retype)) 
9490                 genUnpackBits(result,"BAD",GPOINTER);
9491
9492         release:
9493         pic16_freeAsmop(left,NULL,ic,TRUE);
9494         pic16_freeAsmop(result,NULL,ic,TRUE);
9495
9496 }
9497
9498 /*-----------------------------------------------------------------*/
9499 /* genConstPointerGet - get value from const generic pointer space */
9500 /*-----------------------------------------------------------------*/
9501 static void genConstPointerGet (operand *left,
9502                                 operand *result, iCode *ic)
9503 {
9504   //sym_link *retype = getSpec(operandType(result));
9505   // symbol *albl = newiTempLabel(NULL);        // patch 15
9506   // symbol *blbl = newiTempLabel(NULL);        //
9507   // PIC_OPCODE poc;                            // patch 15
9508   int size;
9509   int offset = 0;
9510
9511   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9512   pic16_aopOp(left,ic,FALSE);
9513   pic16_aopOp(result,ic,TRUE);
9514   size = AOP_SIZE(result);
9515
9516   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9517
9518   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9519 #if 0                                                                   // patch 15
9520   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9521   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9522   pic16_emitpLabel(albl->key);
9523
9524   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9525     
9526   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9527   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9528   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9529   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9530   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9531
9532   pic16_emitpLabel(blbl->key);
9533
9534   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9535 #endif                                                                  // patch 15
9536
9537
9538   // set up table pointer
9539   if( (AOP_TYPE(left) == AOP_PCODE) 
9540       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9541           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9542     {
9543       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9544       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9545       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9546       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9547       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9548       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9549     }
9550   else
9551     {
9552       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9553       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9554       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9555     }
9556
9557
9558   while(size--)
9559     {
9560       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9561       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9562       offset++;
9563     }
9564                                                                         // .... patch 15
9565   pic16_freeAsmop(left,NULL,ic,TRUE);
9566   pic16_freeAsmop(result,NULL,ic,TRUE);
9567
9568 }
9569 /*-----------------------------------------------------------------*/
9570 /* genPointerGet - generate code for pointer get                   */
9571 /*-----------------------------------------------------------------*/
9572 static void genPointerGet (iCode *ic)
9573 {
9574     operand *left, *result ;
9575     sym_link *type, *etype;
9576     int p_type;
9577
9578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9579
9580     left = IC_LEFT(ic);
9581     result = IC_RESULT(ic) ;
9582
9583     /* depending on the type of pointer we need to
9584     move it to the correct pointer register */
9585     type = operandType(left);
9586     etype = getSpec(type);
9587
9588 #if 0
9589     if (IS_PTR_CONST(type))
9590 #else
9591     if (IS_CODEPTR(type))
9592 #endif
9593       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9594
9595     /* if left is of type of pointer then it is simple */
9596     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9597         p_type = DCL_TYPE(type);
9598     else {
9599         /* we have to go by the storage class */
9600         p_type = PTR_TYPE(SPEC_OCLS(etype));
9601
9602         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9603
9604         if (SPEC_OCLS(etype)->codesp ) {
9605           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9606           //p_type = CPOINTER ; 
9607         }
9608         else
9609             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9610               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9611                /*p_type = FPOINTER ;*/ 
9612             else
9613                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9614                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9615 /*                  p_type = PPOINTER; */
9616                 else
9617                     if (SPEC_OCLS(etype) == idata )
9618                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9619 /*                      p_type = IPOINTER; */
9620                     else
9621                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9622 /*                      p_type = POINTER ; */
9623     }
9624
9625     /* now that we have the pointer type we assign
9626     the pointer values */
9627     switch (p_type) {
9628
9629     case POINTER:       
9630     case IPOINTER:
9631         genNearPointerGet (left,result,ic);
9632         break;
9633
9634     case PPOINTER:
9635         genPagedPointerGet(left,result,ic);
9636         break;
9637
9638     case FPOINTER:
9639         genFarPointerGet (left,result,ic);
9640         break;
9641
9642     case CPOINTER:
9643         genConstPointerGet (left,result,ic);
9644         //pic16_emitcodePointerGet (left,result,ic);
9645         break;
9646
9647     case GPOINTER:
9648 #if 0
9649       if (IS_PTR_CONST(type))
9650         genConstPointerGet (left,result,ic);
9651       else
9652 #endif
9653         genGenPointerGet (left,result,ic);
9654       break;
9655     }
9656
9657 }
9658
9659 /*-----------------------------------------------------------------*/
9660 /* genPackBits - generates code for packed bit storage             */
9661 /*-----------------------------------------------------------------*/
9662 static void genPackBits (sym_link    *etype ,
9663                          operand *right ,
9664                          char *rname, int p_type)
9665 {
9666   int shCnt = 0 ;
9667   int offset = 0  ;
9668   int rLen = 0 ;
9669   int blen, bstr ;   
9670   char *l ;
9671
9672         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9673         blen = SPEC_BLEN(etype);
9674         bstr = SPEC_BSTR(etype);
9675
9676         if(AOP_TYPE(right) == AOP_LIT) {
9677                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9678                 offset++;
9679         } else
9680                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9681
9682 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9683         MOVA(l);   
9684 */
9685         /* if the bit lenth is less than or    */
9686         /* it exactly fits a byte then         */
9687         if((shCnt=SPEC_BSTR(etype))
9688                 || SPEC_BLEN(etype) <= 8 )  {
9689
9690                 /* shift left acc */
9691                 AccLsh(shCnt);
9692
9693                 /* using PRODL as a temporary register here */
9694                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9695
9696                 switch (p_type) {
9697                         case FPOINTER:
9698                         case POINTER:
9699                         case GPOINTER:
9700                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9701 //                              pic16_emitcode ("mov","b,a");
9702 //                              pic16_emitcode("mov","a,@%s",rname);
9703                                 break;
9704                 }
9705 #if 1
9706                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9707                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9708                                         (unsigned char)(0xff >> (8-bstr))) ));
9709                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9710                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9711 #endif
9712
9713 #if 0
9714                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9715                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9716                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9717                 pic16_emitcode ("orl","a,b");
9718                 if (p_type == GPOINTER)
9719                         pic16_emitcode("pop","b");
9720
9721                 
9722                 switch (p_type) {
9723                         case POINTER:
9724                                 pic16_emitcode("mov","@%s,a",rname);
9725                                 break;
9726                         case FPOINTER:
9727                                 pic16_emitcode("movx","@dptr,a");
9728                                 break;
9729                         case GPOINTER:
9730                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9731                                 break;
9732                 }
9733 #endif
9734
9735           return;
9736         }
9737
9738
9739         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9740         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9741         exit(-1);
9742
9743
9744     /* if we r done */
9745     if ( SPEC_BLEN(etype) <= 8 )
9746         return ;
9747
9748     pic16_emitcode("inc","%s",rname);
9749     rLen = SPEC_BLEN(etype) ;     
9750
9751
9752
9753     /* now generate for lengths greater than one byte */
9754     while (1) {
9755
9756         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9757
9758         rLen -= 8 ;
9759         if (rLen <= 0 )
9760             break ;
9761
9762         switch (p_type) {
9763             case POINTER:
9764                 if (*l == '@') {
9765                     MOVA(l);
9766                     pic16_emitcode("mov","@%s,a",rname);
9767                 } else
9768                     pic16_emitcode("mov","@%s,%s",rname,l);
9769                 break;
9770
9771             case FPOINTER:
9772                 MOVA(l);
9773                 pic16_emitcode("movx","@dptr,a");
9774                 break;
9775
9776             case GPOINTER:
9777                 MOVA(l);
9778                 DEBUGpic16_emitcode(";lcall","__gptrput");
9779                 break;  
9780         }   
9781         pic16_emitcode ("inc","%s",rname);
9782     }
9783
9784     MOVA(l);
9785
9786     /* last last was not complete */
9787     if (rLen)   {
9788         /* save the byte & read byte */
9789         switch (p_type) {
9790             case POINTER:
9791                 pic16_emitcode ("mov","b,a");
9792                 pic16_emitcode("mov","a,@%s",rname);
9793                 break;
9794
9795             case FPOINTER:
9796                 pic16_emitcode ("mov","b,a");
9797                 pic16_emitcode("movx","a,@dptr");
9798                 break;
9799
9800             case GPOINTER:
9801                 pic16_emitcode ("push","b");
9802                 pic16_emitcode ("push","acc");
9803                 pic16_emitcode ("lcall","__gptrget");
9804                 pic16_emitcode ("pop","b");
9805                 break;
9806         }
9807
9808         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9809         pic16_emitcode ("orl","a,b");
9810     }
9811
9812     if (p_type == GPOINTER)
9813         pic16_emitcode("pop","b");
9814
9815     switch (p_type) {
9816
9817     case POINTER:
9818         pic16_emitcode("mov","@%s,a",rname);
9819         break;
9820         
9821     case FPOINTER:
9822         pic16_emitcode("movx","@dptr,a");
9823         break;
9824         
9825     case GPOINTER:
9826         DEBUGpic16_emitcode(";lcall","__gptrput");
9827         break;                  
9828     }
9829 }
9830 /*-----------------------------------------------------------------*/
9831 /* genDataPointerSet - remat pointer to data space                 */
9832 /*-----------------------------------------------------------------*/
9833 static void genDataPointerSet(operand *right,
9834                               operand *result,
9835                               iCode *ic)
9836 {
9837     int size, offset = 0, resoffset=0 ;
9838
9839     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9840     pic16_aopOp(right,ic,FALSE);
9841
9842     size = AOP_SIZE(right);
9843
9844 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9845
9846 #if 0
9847     if ( AOP_TYPE(result) == AOP_PCODE) {
9848       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9849               AOP(result)->aopu.pcop->name,
9850                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9851               PCOR(AOP(result)->aopu.pcop)->instance:
9852               PCOI(AOP(result)->aopu.pcop)->offset);
9853     }
9854 #endif
9855
9856         if(AOP(result)->aopu.pcop->type == PO_DIR)
9857                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9858
9859         while (size--) {
9860                 if (AOP_TYPE(right) == AOP_LIT) {
9861                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9862
9863                         lit = lit >> (8*offset);
9864                         if(lit&0xff) {
9865                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9866                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9867                         } else {
9868                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9869                         }
9870                 } else {
9871                         mov2w(AOP(right), offset);
9872                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9873                 }
9874                 offset++;
9875                 resoffset++;
9876         }
9877
9878     pic16_freeAsmop(right,NULL,ic,TRUE);
9879 }
9880
9881
9882
9883 /*-----------------------------------------------------------------*/
9884 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9885 /*-----------------------------------------------------------------*/
9886 static void genNearPointerSet (operand *right,
9887                                operand *result, 
9888                                iCode *ic)
9889 {
9890   asmop *aop = NULL;
9891   char *l;
9892   sym_link *retype;
9893   sym_link *ptype = operandType(result);
9894   sym_link *resetype;
9895     
9896         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9897         retype= getSpec(operandType(right));
9898         resetype = getSpec(operandType(result));
9899   
9900         pic16_aopOp(result,ic,FALSE);
9901     
9902         /* if the result is rematerializable &
9903          * in data space & not a bit variable */
9904         
9905         /* and result is not a bit variable */
9906         if (AOP_TYPE(result) == AOP_PCODE
9907 //              && AOP_TYPE(result) == AOP_IMMD
9908                 && DCL_TYPE(ptype) == POINTER
9909                 && !IS_BITFIELD(retype)
9910                 && !IS_BITFIELD(resetype)) {
9911
9912                 genDataPointerSet (right,result,ic);
9913                 pic16_freeAsmop(result,NULL,ic,TRUE);
9914           return;
9915         }
9916
9917         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9918         pic16_aopOp(right,ic,FALSE);
9919         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9920
9921         /* if the value is already in a pointer register
9922          * then don't need anything more */
9923         if (!AOP_INPREG(AOP(result))) {
9924                 /* otherwise get a free pointer register */
9925                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9926
9927                 if( (AOP_TYPE(result) == AOP_PCODE) 
9928                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9929                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9930                 {
9931                         pic16_loadFSR0( result );  // patch 10
9932                 } else {
9933                         // set up FSR0 with address of result
9934                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9935                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9936                 }
9937
9938         }
9939 //      else
9940 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9941
9942         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9943
9944         /* if bitfield then unpack the bits */
9945         if (IS_BITFIELD(resetype)) {
9946                 genPackBits (resetype, right, NULL, POINTER);
9947         } else {
9948                 /* we have can just get the values */
9949           int size = AOP_SIZE(right);
9950           int offset = 0 ;    
9951
9952                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9953                 while (size--) {
9954                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9955                         if (*l == '@' ) {
9956                                 //MOVA(l);
9957                                 //pic16_emitcode("mov","@%s,a",rname);
9958                                 pic16_emitcode("movf","indf0,w ;1");
9959                         } else {
9960
9961                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9962                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9963                                         if (size) {                                                                     // 
9964                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9965                                         } else {                                                                        // 
9966                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9967                                         }                                                                               // 
9968                                 } else { // no literal                                                                  // 
9969                                         if(size) {                                                                      // 
9970                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9971                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9972                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9973                                         } else {                                                                        // 
9974                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9975                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9976                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9977                                         }                                                                               //
9978                                 }                                                                                       // patch 10
9979                         }
9980                         offset++;
9981                 }
9982         }
9983
9984         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9985         /* now some housekeeping stuff */
9986         if (aop) {
9987                 /* we had to allocate for this iCode */
9988                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9989         } else { 
9990                 /* we did not allocate which means left
9991                  * already in a pointer register, then
9992                  * if size > 0 && this could be used again
9993                  * we have to point it back to where it 
9994                  * belongs */
9995                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9996                 if (AOP_SIZE(right) > 1
9997                         && !OP_SYMBOL(result)->remat
9998                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9999                                 || ic->depth )) {
10000
10001                   int size = AOP_SIZE(right) - 1;
10002
10003                         while (size--)
10004                                 pic16_emitcode("decf","fsr0,f");
10005                         //pic16_emitcode("dec","%s",rname);
10006                 }
10007         }
10008
10009         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10010         /* done */
10011 //release:
10012         pic16_freeAsmop(right,NULL,ic,TRUE);
10013         pic16_freeAsmop(result,NULL,ic,TRUE);
10014 }
10015
10016 /*-----------------------------------------------------------------*/
10017 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10018 /*-----------------------------------------------------------------*/
10019 static void genPagedPointerSet (operand *right,
10020                                operand *result, 
10021                                iCode *ic)
10022 {
10023     asmop *aop = NULL;
10024     regs *preg = NULL ;
10025     char *rname , *l;
10026     sym_link *retype;
10027        
10028     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10029
10030     retype= getSpec(operandType(right));
10031     
10032     pic16_aopOp(result,ic,FALSE);
10033     
10034     /* if the value is already in a pointer register
10035        then don't need anything more */
10036     if (!AOP_INPREG(AOP(result))) {
10037         /* otherwise get a free pointer register */
10038         aop = newAsmop(0);
10039         preg = getFreePtr(ic,&aop,FALSE);
10040         pic16_emitcode("mov","%s,%s",
10041                 preg->name,
10042                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10043         rname = preg->name ;
10044     } else
10045         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10046     
10047     pic16_freeAsmop(result,NULL,ic,TRUE);
10048     pic16_aopOp (right,ic,FALSE);
10049
10050     /* if bitfield then unpack the bits */
10051     if (IS_BITFIELD(retype)) 
10052         genPackBits (retype,right,rname,PPOINTER);
10053     else {
10054         /* we have can just get the values */
10055         int size = AOP_SIZE(right);
10056         int offset = 0 ;        
10057         
10058         while (size--) {
10059             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10060             
10061             MOVA(l);
10062             pic16_emitcode("movx","@%s,a",rname);
10063
10064             if (size)
10065                 pic16_emitcode("inc","%s",rname);
10066
10067             offset++;
10068         }
10069     }
10070     
10071     /* now some housekeeping stuff */
10072     if (aop) {
10073         /* we had to allocate for this iCode */
10074         pic16_freeAsmop(NULL,aop,ic,TRUE);
10075     } else { 
10076         /* we did not allocate which means left
10077            already in a pointer register, then
10078            if size > 0 && this could be used again
10079            we have to point it back to where it 
10080            belongs */
10081         if (AOP_SIZE(right) > 1 &&
10082             !OP_SYMBOL(result)->remat &&
10083             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10084               ic->depth )) {
10085             int size = AOP_SIZE(right) - 1;
10086             while (size--)
10087                 pic16_emitcode("dec","%s",rname);
10088         }
10089     }
10090
10091     /* done */
10092     pic16_freeAsmop(right,NULL,ic,TRUE);
10093     
10094         
10095 }
10096
10097 /*-----------------------------------------------------------------*/
10098 /* genFarPointerSet - set value from far space                     */
10099 /*-----------------------------------------------------------------*/
10100 static void genFarPointerSet (operand *right,
10101                               operand *result, iCode *ic)
10102 {
10103     int size, offset ;
10104     sym_link *retype = getSpec(operandType(right));
10105
10106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10107     pic16_aopOp(result,ic,FALSE);
10108
10109     /* if the operand is already in dptr 
10110     then we do nothing else we move the value to dptr */
10111     if (AOP_TYPE(result) != AOP_STR) {
10112         /* if this is remateriazable */
10113         if (AOP_TYPE(result) == AOP_IMMD)
10114             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10115         else { /* we need to get it byte by byte */
10116             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10117             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10118             if (options.model == MODEL_FLAT24)
10119             {
10120                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10121             }
10122         }
10123     }
10124     /* so dptr know contains the address */
10125     pic16_freeAsmop(result,NULL,ic,TRUE);
10126     pic16_aopOp(right,ic,FALSE);
10127
10128     /* if bit then unpack */
10129     if (IS_BITFIELD(retype)) 
10130         genPackBits(retype,right,"dptr",FPOINTER);
10131     else {
10132         size = AOP_SIZE(right);
10133         offset = 0 ;
10134
10135         while (size--) {
10136             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10137             MOVA(l);
10138             pic16_emitcode("movx","@dptr,a");
10139             if (size)
10140                 pic16_emitcode("inc","dptr");
10141         }
10142     }
10143
10144     pic16_freeAsmop(right,NULL,ic,TRUE);
10145 }
10146
10147 /*-----------------------------------------------------------------*/
10148 /* genGenPointerSet - set value from generic pointer space         */
10149 /*-----------------------------------------------------------------*/
10150 static void genGenPointerSet (operand *right,
10151                               operand *result, iCode *ic)
10152 {
10153         int i, size, offset, lit;
10154         sym_link *retype = getSpec(operandType(right));
10155
10156         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10157
10158         pic16_aopOp(result,ic,FALSE);
10159         pic16_aopOp(right,ic,FALSE);
10160         size = AOP_SIZE(right);
10161         offset = 0;
10162
10163         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10164
10165         /* if the operand is already in dptr 
10166                 then we do nothing else we move the value to dptr */
10167         if (AOP_TYPE(result) != AOP_STR) {
10168                 /* if this is remateriazable */
10169                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10170                 // WARNING: anythig until "else" is untested!
10171                 if (AOP_TYPE(result) == AOP_IMMD) {
10172                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10173                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10174                         // load FSR0 from immediate
10175                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10176                         offset = 0;
10177                         while(size--) {
10178                                 if(size) {
10179                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10180                                 } else {
10181                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10182                                 }
10183                                 offset++;
10184                         }
10185                         goto release;
10186                 }
10187                 else { /* we need to get it byte by byte */
10188                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10189                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10190
10191                         // set up FSR0 with address of result
10192                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10193                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10194
10195                         /* hack hack! see if this the FSR. If so don't load W */
10196                         if(AOP_TYPE(right) != AOP_ACC) {
10197
10198                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10199
10200                                 if(AOP_TYPE(right) == AOP_LIT)
10201                                 {
10202                                         // copy literal
10203                                         // note: pic16_popGet handles sign extension
10204                                         for(i=0;i<size;i++) {
10205                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10206                                                 if(i < size-1)
10207                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10208                                                 else
10209                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10210                                         }
10211                                 } else {
10212                                         // copy regs
10213
10214                                         for(i=0;i<size;i++) {
10215                                                 if(i < size-1)
10216                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10217                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10218                                                 else
10219                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10220                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10221                                         }
10222                                 }
10223                                 goto release;
10224                         } 
10225                         // right = ACC
10226                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10227                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10228                         goto release;
10229         } // if (AOP_TYPE(result) != AOP_IMMD)
10230
10231         } // if (AOP_TYPE(result) != AOP_STR)
10232         /* so dptr know contains the address */
10233
10234
10235         /* if bit then unpack */
10236         if (IS_BITFIELD(retype)) 
10237                 genPackBits(retype,right,"dptr",GPOINTER);
10238         else {
10239                 size = AOP_SIZE(right);
10240                 offset = 0 ;
10241
10242                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10243
10244                 // set up FSR0 with address of result
10245                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10246                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10247         
10248                 while (size--) {
10249                         if (AOP_TYPE(right) == AOP_LIT) {
10250                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10251                                 if (size) {
10252                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10253                                 } else {
10254                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10255                                 }
10256                         } else { // no literal
10257                                 if(size) {
10258                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10259                                 } else {
10260                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10261                                 }
10262                         }
10263                         offset++;
10264                 }
10265         }
10266
10267         release:
10268         pic16_freeAsmop(right,NULL,ic,TRUE);
10269         pic16_freeAsmop(result,NULL,ic,TRUE);
10270 }
10271
10272 /*-----------------------------------------------------------------*/
10273 /* genPointerSet - stores the value into a pointer location        */
10274 /*-----------------------------------------------------------------*/
10275 static void genPointerSet (iCode *ic)
10276 {    
10277     operand *right, *result ;
10278     sym_link *type, *etype;
10279     int p_type;
10280
10281     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10282
10283     right = IC_RIGHT(ic);
10284     result = IC_RESULT(ic) ;
10285
10286     /* depending on the type of pointer we need to
10287     move it to the correct pointer register */
10288     type = operandType(result);
10289     etype = getSpec(type);
10290     /* if left is of type of pointer then it is simple */
10291     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10292         p_type = DCL_TYPE(type);
10293     }
10294     else {
10295         /* we have to go by the storage class */
10296         p_type = PTR_TYPE(SPEC_OCLS(etype));
10297
10298 /*      if (SPEC_OCLS(etype)->codesp ) { */
10299 /*          p_type = CPOINTER ;  */
10300 /*      } */
10301 /*      else */
10302 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10303 /*              p_type = FPOINTER ; */
10304 /*          else */
10305 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10306 /*                  p_type = PPOINTER ; */
10307 /*              else */
10308 /*                  if (SPEC_OCLS(etype) == idata ) */
10309 /*                      p_type = IPOINTER ; */
10310 /*                  else */
10311 /*                      p_type = POINTER ; */
10312     }
10313
10314     /* now that we have the pointer type we assign
10315     the pointer values */
10316     switch (p_type) {
10317
10318     case POINTER:
10319     case IPOINTER:
10320         genNearPointerSet (right,result,ic);
10321         break;
10322
10323     case PPOINTER:
10324         genPagedPointerSet (right,result,ic);
10325         break;
10326
10327     case FPOINTER:
10328         genFarPointerSet (right,result,ic);
10329         break;
10330
10331     case GPOINTER:
10332         genGenPointerSet (right,result,ic);
10333         break;
10334
10335     default:
10336       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10337               "genPointerSet: illegal pointer type");
10338     }
10339 }
10340
10341 /*-----------------------------------------------------------------*/
10342 /* genIfx - generate code for Ifx statement                        */
10343 /*-----------------------------------------------------------------*/
10344 static void genIfx (iCode *ic, iCode *popIc)
10345 {
10346   operand *cond = IC_COND(ic);
10347   int isbit =0;
10348
10349   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10350
10351   pic16_aopOp(cond,ic,FALSE);
10352
10353   /* get the value into acc */
10354   if (AOP_TYPE(cond) != AOP_CRY)
10355     pic16_toBoolean(cond);
10356   else
10357     isbit = 1;
10358   /* the result is now in the accumulator */
10359   pic16_freeAsmop(cond,NULL,ic,TRUE);
10360
10361   /* if there was something to be popped then do it */
10362   if (popIc)
10363     genIpop(popIc);
10364
10365   /* if the condition is  a bit variable */
10366   if (isbit && IS_ITEMP(cond) && 
10367       SPIL_LOC(cond)) {
10368     genIfxJump(ic,SPIL_LOC(cond)->rname);
10369     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10370   }
10371   else {
10372     if (isbit && !IS_ITEMP(cond))
10373       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10374     else
10375       genIfxJump(ic,"a");
10376   }
10377   ic->generated = 1;
10378
10379 }
10380
10381 /*-----------------------------------------------------------------*/
10382 /* genAddrOf - generates code for address of                       */
10383 /*-----------------------------------------------------------------*/
10384 static void genAddrOf (iCode *ic)
10385 {
10386   operand *result, *left;
10387   int size;
10388   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10389   pCodeOp *pcop0, *pcop1, *pcop2;
10390
10391         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10392
10393         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10394         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10395
10396         sym = OP_SYMBOL( left );
10397
10398         size = AOP_SIZE(IC_RESULT(ic));
10399
10400         if(pic16_debug_verbose) {
10401                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10402                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10403         }
10404         
10405         /* Assume that what we want the address of is in data space
10406          * since there is no stack on the PIC, yet! -- VR */
10407         /* low */
10408         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10409
10410         /* high */
10411         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10412         
10413         /* upper */
10414         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10415         
10416
10417         if (size == 3) {
10418                 pic16_emitpcode(POC_MOVLW, pcop0);
10419                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10420                 pic16_emitpcode(POC_MOVLW, pcop1);
10421                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10422                 pic16_emitpcode(POC_MOVLW, pcop2);
10423                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10424         } else
10425         if (size == 2) {
10426                 pic16_emitpcode(POC_MOVLW, pcop0);
10427                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10428                 pic16_emitpcode(POC_MOVLW, pcop1);
10429                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10430         } else {
10431                 pic16_emitpcode(POC_MOVLW, pcop0);
10432                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10433         }
10434
10435         pic16_freeAsmop(result,NULL,ic,TRUE);
10436         pic16_freeAsmop(left, NULL, ic, FALSE);
10437 }
10438
10439
10440 #if 0
10441 /*-----------------------------------------------------------------*/
10442 /* genFarFarAssign - assignment when both are in far space         */
10443 /*-----------------------------------------------------------------*/
10444 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10445 {
10446     int size = AOP_SIZE(right);
10447     int offset = 0;
10448     char *l ;
10449     /* first push the right side on to the stack */
10450     while (size--) {
10451         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10452         MOVA(l);
10453         pic16_emitcode ("push","acc");
10454     }
10455     
10456     pic16_freeAsmop(right,NULL,ic,FALSE);
10457     /* now assign DPTR to result */
10458     pic16_aopOp(result,ic,FALSE);
10459     size = AOP_SIZE(result);
10460     while (size--) {
10461         pic16_emitcode ("pop","acc");
10462         pic16_aopPut(AOP(result),"a",--offset);
10463     }
10464     pic16_freeAsmop(result,NULL,ic,FALSE);
10465         
10466 }
10467 #endif
10468
10469 /*-----------------------------------------------------------------*/
10470 /* genAssign - generate code for assignment                        */
10471 /*-----------------------------------------------------------------*/
10472 static void genAssign (iCode *ic)
10473 {
10474   operand *result, *right;
10475   int size, offset,know_W;
10476   unsigned long lit = 0L;
10477
10478   result = IC_RESULT(ic);
10479   right  = IC_RIGHT(ic) ;
10480
10481   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10482   
10483   /* if they are the same */
10484   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10485     return ;
10486
10487   pic16_aopOp(right,ic,FALSE);
10488   pic16_aopOp(result,ic,TRUE);
10489
10490   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10491
10492   /* if they are the same registers */
10493   if (pic16_sameRegs(AOP(right),AOP(result)))
10494     goto release;
10495
10496   /* if the result is a bit */
10497   if (AOP_TYPE(result) == AOP_CRY) {
10498     /* if the right size is a literal then
10499        we know what the value is */
10500     if (AOP_TYPE(right) == AOP_LIT) {
10501           
10502       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10503                   pic16_popGet(AOP(result),0));
10504
10505       if (((int) operandLitValue(right))) 
10506         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10507                        AOP(result)->aopu.aop_dir,
10508                        AOP(result)->aopu.aop_dir);
10509       else
10510         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10511                        AOP(result)->aopu.aop_dir,
10512                        AOP(result)->aopu.aop_dir);
10513       goto release;
10514     }
10515
10516     /* the right is also a bit variable */
10517     if (AOP_TYPE(right) == AOP_CRY) {
10518       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10519       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10520       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10521
10522       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10523                      AOP(result)->aopu.aop_dir,
10524                      AOP(result)->aopu.aop_dir);
10525       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10526                      AOP(right)->aopu.aop_dir,
10527                      AOP(right)->aopu.aop_dir);
10528       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10529                      AOP(result)->aopu.aop_dir,
10530                      AOP(result)->aopu.aop_dir);
10531       goto release ;
10532     }
10533
10534     /* we need to or */
10535     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10536     pic16_toBoolean(right);
10537     emitSKPZ;
10538     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10539     //pic16_aopPut(AOP(result),"a",0);
10540     goto release ;
10541   }
10542
10543   /* bit variables done */
10544   /* general case */
10545   size = AOP_SIZE(result);
10546   offset = 0 ;
10547   if(AOP_TYPE(right) == AOP_LIT)
10548     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10549
10550 /* VR - What is this?! */
10551   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10552   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10553     if(aopIdx(AOP(result),0) == 4) {
10554   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10555       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10556       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10557       goto release;
10558     } else
10559       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10560   }
10561
10562   know_W=-1;
10563   while (size--) {
10564   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10565     if(AOP_TYPE(right) == AOP_LIT) {
10566       if(lit&0xff) {
10567         if(know_W != (lit&0xff))
10568           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10569         know_W = lit&0xff;
10570         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10571       } else
10572         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10573
10574       lit >>= 8;
10575
10576     } else if (AOP_TYPE(right) == AOP_CRY) {
10577       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10578       if(offset == 0) {
10579         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10580         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10581       }
10582     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10583         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10584         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10585     } else {
10586   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10587
10588 #if 1
10589         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10590            normally should work, but mind that the W register live range
10591            is not checked, so if the code generator assumes that the W
10592            is already loaded after such a pair, wrong code will be generated.
10593            
10594            Checking the live range is the next step.
10595            This is experimental code yet and has not been fully tested yet.
10596            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10597            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10598            
10599         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10600 #else   
10601         /* This is the old code, which is assumed(?!) that works fine(!?) */
10602
10603         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10604         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10605 #endif
10606     }
10607             
10608     offset++;
10609   }
10610
10611     
10612  release:
10613   pic16_freeAsmop (right,NULL,ic,FALSE);
10614   pic16_freeAsmop (result,NULL,ic,TRUE);
10615 }   
10616
10617 /*-----------------------------------------------------------------*/
10618 /* genJumpTab - generates code for jump table                       */
10619 /*-----------------------------------------------------------------*/
10620 static void genJumpTab (iCode *ic)
10621 {
10622     symbol *jtab;
10623     char *l;
10624
10625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10626
10627     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10628     /* get the condition into accumulator */
10629     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10630     MOVA(l);
10631     /* multiply by three */
10632     pic16_emitcode("add","a,acc");
10633     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10634
10635     jtab = newiTempLabel(NULL);
10636     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10637     pic16_emitcode("jmp","@a+dptr");
10638     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10639
10640     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10641     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10642     emitSKPNC;
10643     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10644     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10645     pic16_emitpLabel(jtab->key);
10646
10647     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10648
10649     /* now generate the jump labels */
10650     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10651          jtab = setNextItem(IC_JTLABELS(ic))) {
10652         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10653         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10654         
10655     }
10656
10657 }
10658
10659 /*-----------------------------------------------------------------*/
10660 /* genMixedOperation - gen code for operators between mixed types  */
10661 /*-----------------------------------------------------------------*/
10662 /*
10663   TSD - Written for the PIC port - but this unfortunately is buggy.
10664   This routine is good in that it is able to efficiently promote 
10665   types to different (larger) sizes. Unfortunately, the temporary
10666   variables that are optimized out by this routine are sometimes
10667   used in other places. So until I know how to really parse the 
10668   iCode tree, I'm going to not be using this routine :(.
10669 */
10670 static int genMixedOperation (iCode *ic)
10671 {
10672 #if 0
10673   operand *result = IC_RESULT(ic);
10674   sym_link *ctype = operandType(IC_LEFT(ic));
10675   operand *right = IC_RIGHT(ic);
10676   int ret = 0;
10677   int big,small;
10678   int offset;
10679
10680   iCode *nextic;
10681   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10682
10683   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10684
10685   nextic = ic->next;
10686   if(!nextic)
10687     return 0;
10688
10689   nextright = IC_RIGHT(nextic);
10690   nextleft  = IC_LEFT(nextic);
10691   nextresult = IC_RESULT(nextic);
10692
10693   pic16_aopOp(right,ic,FALSE);
10694   pic16_aopOp(result,ic,FALSE);
10695   pic16_aopOp(nextright,  nextic, FALSE);
10696   pic16_aopOp(nextleft,   nextic, FALSE);
10697   pic16_aopOp(nextresult, nextic, FALSE);
10698
10699   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10700
10701     operand *t = right;
10702     right = nextright;
10703     nextright = t; 
10704
10705     pic16_emitcode(";remove right +","");
10706
10707   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10708 /*
10709     operand *t = right;
10710     right = nextleft;
10711     nextleft = t; 
10712 */
10713     pic16_emitcode(";remove left +","");
10714   } else
10715     return 0;
10716
10717   big = AOP_SIZE(nextleft);
10718   small = AOP_SIZE(nextright);
10719
10720   switch(nextic->op) {
10721
10722   case '+':
10723     pic16_emitcode(";optimize a +","");
10724     /* if unsigned or not an integral type */
10725     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10726       pic16_emitcode(";add a bit to something","");
10727     } else {
10728
10729       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10730
10731       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10732         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10733         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10734       } else
10735         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10736
10737       offset = 0;
10738       while(--big) {
10739
10740         offset++;
10741
10742         if(--small) {
10743           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10744             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10745             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10746           }
10747
10748           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10749           emitSKPNC;
10750           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10751                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10752                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10753           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10754           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10755
10756         } else {
10757           pic16_emitcode("rlf","known_zero,w");
10758
10759           /*
10760             if right is signed
10761               btfsc  right,7
10762                addlw ff
10763           */
10764           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10765             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10766             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10767           } else {
10768             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10769           }
10770         }
10771       }
10772       ret = 1;
10773     }
10774   }
10775   ret = 1;
10776
10777 release:
10778   pic16_freeAsmop(right,NULL,ic,TRUE);
10779   pic16_freeAsmop(result,NULL,ic,TRUE);
10780   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10781   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10782   if(ret)
10783     nextic->generated = 1;
10784
10785   return ret;
10786 #else
10787   return 0;
10788 #endif
10789 }
10790 /*-----------------------------------------------------------------*/
10791 /* genCast - gen code for casting                                  */
10792 /*-----------------------------------------------------------------*/
10793 static void genCast (iCode *ic)
10794 {
10795   operand *result = IC_RESULT(ic);
10796   sym_link *ctype = operandType(IC_LEFT(ic));
10797   sym_link *rtype = operandType(IC_RIGHT(ic));
10798   operand *right = IC_RIGHT(ic);
10799   int size, offset ;
10800
10801         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10802         /* if they are equivalent then do nothing */
10803         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10804                 return ;
10805
10806         pic16_aopOp(right,ic,FALSE) ;
10807         pic16_aopOp(result,ic,FALSE);
10808
10809         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10810
10811         /* if the result is a bit */
10812         if (AOP_TYPE(result) == AOP_CRY) {
10813         
10814                 /* if the right size is a literal then
10815                  * we know what the value is */
10816                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10817
10818                 if (AOP_TYPE(right) == AOP_LIT) {
10819                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10820                                 pic16_popGet(AOP(result),0));
10821
10822                         if (((int) operandLitValue(right))) 
10823                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10824                                         AOP(result)->aopu.aop_dir,
10825                                         AOP(result)->aopu.aop_dir);
10826                         else
10827                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10828                                         AOP(result)->aopu.aop_dir,
10829                                         AOP(result)->aopu.aop_dir);
10830                         goto release;
10831                 }
10832
10833                 /* the right is also a bit variable */
10834                 if (AOP_TYPE(right) == AOP_CRY) {
10835                         emitCLRC;
10836                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10837
10838                         pic16_emitcode("clrc","");
10839                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10840                                 AOP(right)->aopu.aop_dir,
10841                                 AOP(right)->aopu.aop_dir);
10842                         pic16_aopPut(AOP(result),"c",0);
10843                         goto release ;
10844                 }
10845
10846                 /* we need to or */
10847                 if (AOP_TYPE(right) == AOP_REG) {
10848                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10849                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10850                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10851                 }
10852                 pic16_toBoolean(right);
10853                 pic16_aopPut(AOP(result),"a",0);
10854                 goto release ;
10855         }
10856
10857         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10858           int offset = 1;
10859
10860                 size = AOP_SIZE(result);
10861
10862                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10863
10864                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10865                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10866                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10867
10868                 while (size--)
10869                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10870
10871                 goto release;
10872         }
10873
10874         /* if they are the same size : or less */
10875         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10876
10877                 /* if they are in the same place */
10878                 if (pic16_sameRegs(AOP(right),AOP(result)))
10879                         goto release;
10880
10881                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10882 #if 0
10883                 if (IS_PTR_CONST(rtype))
10884 #else
10885                 if (IS_CODEPTR(rtype))
10886 #endif
10887                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10888
10889 #if 0
10890                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10891 #else
10892                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10893 #endif
10894                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10895
10896 #if 0
10897                 if(AOP_TYPE(right) == AOP_IMMD) {
10898                   pCodeOp *pcop0, *pcop1, *pcop2;
10899                   symbol *sym = OP_SYMBOL( right );
10900
10901                         size = AOP_SIZE(result);
10902                         /* low */
10903                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10904                         /* high */
10905                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10906                         /* upper */
10907                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10908         
10909                         if (size == 3) {
10910                                 pic16_emitpcode(POC_MOVLW, pcop0);
10911                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10912                                 pic16_emitpcode(POC_MOVLW, pcop1);
10913                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10914                                 pic16_emitpcode(POC_MOVLW, pcop2);
10915                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10916                         } else
10917                         if (size == 2) {
10918                                 pic16_emitpcode(POC_MOVLW, pcop0);
10919                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10920                                 pic16_emitpcode(POC_MOVLW, pcop1);
10921                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10922                         } else {
10923                                 pic16_emitpcode(POC_MOVLW, pcop0);
10924                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10925                         }
10926                 } else
10927 #endif
10928                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10929                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10930                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10931                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10932                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10933                         if(AOP_SIZE(result) <2)
10934                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10935                 } else {
10936                         /* if they in different places then copy */
10937                         size = AOP_SIZE(result);
10938                         offset = 0 ;
10939                         while (size--) {
10940                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10941                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10942                                 offset++;
10943                         }
10944                 }
10945                 goto release;
10946         }
10947
10948         /* if the result is of type pointer */
10949         if (IS_PTR(ctype)) {
10950           int p_type;
10951           sym_link *type = operandType(right);
10952           sym_link *etype = getSpec(type);
10953
10954                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10955
10956                 /* pointer to generic pointer */
10957                 if (IS_GENPTR(ctype)) {
10958                   char *l = zero;
10959             
10960                         if (IS_PTR(type)) 
10961                                 p_type = DCL_TYPE(type);
10962                         else {
10963                 /* we have to go by the storage class */
10964                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10965
10966 /*              if (SPEC_OCLS(etype)->codesp )  */
10967 /*                  p_type = CPOINTER ;  */
10968 /*              else */
10969 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10970 /*                      p_type = FPOINTER ; */
10971 /*                  else */
10972 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10973 /*                          p_type = PPOINTER; */
10974 /*                      else */
10975 /*                          if (SPEC_OCLS(etype) == idata ) */
10976 /*                              p_type = IPOINTER ; */
10977 /*                          else */
10978 /*                              p_type = POINTER ; */
10979             }
10980                 
10981             /* the first two bytes are known */
10982       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10983             size = GPTRSIZE - 1; 
10984             offset = 0 ;
10985             while (size--) {
10986               if(offset < AOP_SIZE(right)) {
10987       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10988                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10989                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10990                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10991                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10992                 } else { 
10993                   pic16_aopPut(AOP(result),
10994                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10995                          offset);
10996                 }
10997               } else 
10998                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10999               offset++;
11000             }
11001             /* the last byte depending on type */
11002             switch (p_type) {
11003             case IPOINTER:
11004             case POINTER:
11005                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11006                 break;
11007             case FPOINTER:
11008               pic16_emitcode(";BUG!? ","%d",__LINE__);
11009                 l = one;
11010                 break;
11011             case CPOINTER:
11012               pic16_emitcode(";BUG!? ","%d",__LINE__);
11013                 l = "#0x02";
11014                 break;                          
11015             case PPOINTER:
11016               pic16_emitcode(";BUG!? ","%d",__LINE__);
11017                 l = "#0x03";
11018                 break;
11019                 
11020             default:
11021                 /* this should never happen */
11022                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11023                        "got unknown pointer type");
11024                 exit(1);
11025             }
11026             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11027             goto release ;
11028         }
11029         
11030         /* just copy the pointers */
11031         size = AOP_SIZE(result);
11032         offset = 0 ;
11033         while (size--) {
11034             pic16_aopPut(AOP(result),
11035                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11036                    offset);
11037             offset++;
11038         }
11039         goto release ;
11040     }
11041     
11042
11043
11044     /* so we now know that the size of destination is greater
11045     than the size of the source.
11046     Now, if the next iCode is an operator then we might be
11047     able to optimize the operation without performing a cast.
11048     */
11049     if(genMixedOperation(ic))
11050       goto release;
11051
11052     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11053     
11054     /* we move to result for the size of source */
11055     size = AOP_SIZE(right);
11056     offset = 0 ;
11057     while (size--) {
11058       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11059       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11060       offset++;
11061     }
11062
11063     /* now depending on the sign of the destination */
11064     size = AOP_SIZE(result) - AOP_SIZE(right);
11065     /* if unsigned or not an integral type */
11066     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11067       while (size--)
11068         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11069     } else {
11070       /* we need to extend the sign :( */
11071
11072       if(size == 1) {
11073         /* Save one instruction of casting char to int */
11074         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11075         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11076         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11077       } else {
11078         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11079
11080         if(offset)
11081           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11082         else
11083           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11084         
11085         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11086
11087         while (size--)
11088           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11089       }
11090     }
11091
11092 release:
11093     pic16_freeAsmop(right,NULL,ic,TRUE);
11094     pic16_freeAsmop(result,NULL,ic,TRUE);
11095
11096 }
11097
11098 /*-----------------------------------------------------------------*/
11099 /* genDjnz - generate decrement & jump if not zero instrucion      */
11100 /*-----------------------------------------------------------------*/
11101 static int genDjnz (iCode *ic, iCode *ifx)
11102 {
11103     symbol *lbl, *lbl1;
11104     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11105
11106     if (!ifx)
11107         return 0;
11108     
11109     /* if the if condition has a false label
11110        then we cannot save */
11111     if (IC_FALSE(ifx))
11112         return 0;
11113
11114     /* if the minus is not of the form 
11115        a = a - 1 */
11116     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11117         !IS_OP_LITERAL(IC_RIGHT(ic)))
11118         return 0;
11119
11120     if (operandLitValue(IC_RIGHT(ic)) != 1)
11121         return 0;
11122
11123     /* if the size of this greater than one then no
11124        saving */
11125     if (getSize(operandType(IC_RESULT(ic))) > 1)
11126         return 0;
11127
11128     /* otherwise we can save BIG */
11129     lbl = newiTempLabel(NULL);
11130     lbl1= newiTempLabel(NULL);
11131
11132     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11133     
11134     if (IS_AOP_PREG(IC_RESULT(ic))) {
11135         pic16_emitcode("dec","%s",
11136                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11137         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11138         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11139     } else {    
11140
11141
11142       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11143       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11144
11145       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11146       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11147
11148     }
11149 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11150 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11151 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11152 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11153
11154     
11155     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11156     ifx->generated = 1;
11157     return 1;
11158 }
11159
11160 /*-----------------------------------------------------------------*/
11161 /* genReceive - generate code for a receive iCode                  */
11162 /*-----------------------------------------------------------------*/
11163 static void genReceive (iCode *ic)
11164 {    
11165         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11166
11167         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11168                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11169                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11170
11171           int size = getSize(operandType(IC_RESULT(ic)));
11172           int offset =  pic16_fReturnSizePic - size;
11173
11174                 while (size--) {
11175                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11176                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11177                         offset++;
11178                 }
11179
11180                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11181
11182                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11183                 size = AOP_SIZE(IC_RESULT(ic));
11184                 offset = 0;
11185                 while (size--) {
11186                         pic16_emitcode ("pop","acc");
11187                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11188                 }
11189         } else {
11190                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11191
11192                 _G.accInUse++;
11193                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11194                 _G.accInUse--;
11195                 assignResultValue(IC_RESULT(ic), 0);
11196         }
11197
11198         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11199 }
11200
11201 /*-----------------------------------------------------------------*/
11202 /* genDummyRead - generate code for dummy read of volatiles        */
11203 /*-----------------------------------------------------------------*/
11204 static void
11205 genDummyRead (iCode * ic)
11206 {
11207   pic16_emitcode ("; genDummyRead","");
11208   pic16_emitcode ("; not implemented","");
11209
11210   ic = ic;
11211 }
11212
11213 /*-----------------------------------------------------------------*/
11214 /* genpic16Code - generate code for pic16 based controllers        */
11215 /*-----------------------------------------------------------------*/
11216 /*
11217  * At this point, ralloc.c has gone through the iCode and attempted
11218  * to optimize in a way suitable for a PIC. Now we've got to generate
11219  * PIC instructions that correspond to the iCode.
11220  *
11221  * Once the instructions are generated, we'll pass through both the
11222  * peep hole optimizer and the pCode optimizer.
11223  *-----------------------------------------------------------------*/
11224
11225 void genpic16Code (iCode *lic)
11226 {
11227     iCode *ic;
11228     int cln = 0;
11229
11230     lineHead = lineCurr = NULL;
11231
11232     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11233     pic16_addpBlock(pb);
11234
11235 #if 0
11236     /* if debug information required */
11237     if (options.debug && currFunc) {
11238       if (currFunc) {
11239         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11240         _G.debugLine = 1;
11241         if (IS_STATIC(currFunc->etype)) {
11242           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
11243           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
11244         } else {
11245           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
11246           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
11247         }
11248         _G.debugLine = 0;
11249       }
11250     }
11251 #endif
11252
11253     for (ic = lic ; ic ; ic = ic->next ) {
11254
11255       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11256         if ( cln != ic->lineno ) {
11257             if ( options.debug ) {
11258                 _G.debugLine = 1;
11259                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
11260                          FileBaseName(ic->filename),ic->lineno,
11261                          ic->level,ic->block);
11262                 _G.debugLine = 0;
11263             }
11264             
11265             if(!options.noCcodeInAsm) {
11266                 pic16_addpCode2pBlock(pb,
11267                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11268                                 printCLine(ic->filename, ic->lineno)));
11269             }
11270
11271             cln = ic->lineno ;
11272         }
11273         
11274         if(options.iCodeInAsm) {
11275                 char *l;
11276                 /* insert here code to print iCode as comment */
11277                 l = Safe_strdup(printILine(ic));
11278                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11279         }
11280         
11281         /* if the result is marked as
11282            spilt and rematerializable or code for
11283            this has already been generated then
11284            do nothing */
11285         if (resultRemat(ic) || ic->generated ) 
11286             continue ;
11287         
11288         /* depending on the operation */
11289         switch (ic->op) {
11290         case '!' :
11291             pic16_genNot(ic);
11292             break;
11293             
11294         case '~' :
11295             pic16_genCpl(ic);
11296             break;
11297             
11298         case UNARYMINUS:
11299             genUminus (ic);
11300             break;
11301             
11302         case IPUSH:
11303             genIpush (ic);
11304             break;
11305             
11306         case IPOP:
11307             /* IPOP happens only when trying to restore a 
11308                spilt live range, if there is an ifx statement
11309                following this pop then the if statement might
11310                be using some of the registers being popped which
11311                would destroy the contents of the register so
11312                we need to check for this condition and handle it */
11313             if (ic->next            && 
11314                 ic->next->op == IFX &&
11315                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11316                 genIfx (ic->next,ic);
11317             else
11318                 genIpop (ic);
11319             break; 
11320             
11321         case CALL:
11322             genCall (ic);
11323             break;
11324             
11325         case PCALL:
11326             genPcall (ic);
11327             break;
11328             
11329         case FUNCTION:
11330             genFunction (ic);
11331             break;
11332             
11333         case ENDFUNCTION:
11334             genEndFunction (ic);
11335             break;
11336             
11337         case RETURN:
11338             genRet (ic);
11339             break;
11340             
11341         case LABEL:
11342             genLabel (ic);
11343             break;
11344             
11345         case GOTO:
11346             genGoto (ic);
11347             break;
11348             
11349         case '+' :
11350             pic16_genPlus (ic) ;
11351             break;
11352             
11353         case '-' :
11354             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11355                 pic16_genMinus (ic);
11356             break;
11357             
11358         case '*' :
11359             genMult (ic);
11360             break;
11361             
11362         case '/' :
11363             genDiv (ic) ;
11364             break;
11365             
11366         case '%' :
11367             genMod (ic);
11368             break;
11369             
11370         case '>' :
11371             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11372             break;
11373             
11374         case '<' :
11375             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11376             break;
11377             
11378         case LE_OP:
11379         case GE_OP:
11380         case NE_OP:
11381             
11382             /* note these two are xlated by algebraic equivalence
11383                during parsing SDCC.y */
11384             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11385                    "got '>=' or '<=' shouldn't have come here");
11386             break;      
11387             
11388         case EQ_OP:
11389             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11390             break;          
11391             
11392         case AND_OP:
11393             genAndOp (ic);
11394             break;
11395             
11396         case OR_OP:
11397             genOrOp (ic);
11398             break;
11399             
11400         case '^' :
11401             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11402             break;
11403             
11404         case '|' :
11405                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11406             break;
11407             
11408         case BITWISEAND:
11409             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11410             break;
11411             
11412         case INLINEASM:
11413             genInline (ic);
11414             break;
11415             
11416         case RRC:
11417             genRRC (ic);
11418             break;
11419             
11420         case RLC:
11421             genRLC (ic);
11422             break;
11423             
11424         case GETHBIT:
11425             genGetHbit (ic);
11426             break;
11427             
11428         case LEFT_OP:
11429             genLeftShift (ic);
11430             break;
11431             
11432         case RIGHT_OP:
11433             genRightShift (ic);
11434             break;
11435             
11436         case GET_VALUE_AT_ADDRESS:
11437             genPointerGet(ic);
11438             break;
11439             
11440         case '=' :
11441             if (POINTER_SET(ic))
11442                 genPointerSet(ic);
11443             else
11444                 genAssign(ic);
11445             break;
11446             
11447         case IFX:
11448             genIfx (ic,NULL);
11449             break;
11450             
11451         case ADDRESS_OF:
11452             genAddrOf (ic);
11453             break;
11454             
11455         case JUMPTABLE:
11456             genJumpTab (ic);
11457             break;
11458             
11459         case CAST:
11460             genCast (ic);
11461             break;
11462             
11463         case RECEIVE:
11464             genReceive(ic);
11465             break;
11466             
11467         case SEND:
11468             addSet(&_G.sendSet,ic);
11469             break;
11470
11471         case DUMMY_READ_VOLATILE:
11472           genDummyRead (ic);
11473           break;
11474
11475         default :
11476             ic = ic;
11477         }
11478     }
11479
11480
11481     /* now we are ready to call the
11482        peep hole optimizer */
11483     if (!options.nopeep) {
11484       peepHole (&lineHead);
11485     }
11486     /* now do the actual printing */
11487     printLine (lineHead,codeOutFile);
11488
11489 #ifdef PCODE_DEBUG
11490     DFPRINTF((stderr,"printing pBlock\n\n"));
11491     pic16_printpBlock(stdout,pb);
11492 #endif
11493
11494     return;
11495 }
11496