* src/pic16/gen.c (shiftR2Left2Result): fixed bug #1507127
[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              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
66 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
67
68 /* If you change these, you also have to update the library files
69  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
70 #define GPTR_TAG_DATA   0x80
71 #define GPTR_TAG_EEPROM 0x40
72 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
73
74 /* Wrapper to execute `code' at most once. */
75 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
76
77 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
79 void pic16_genMult8X8_8 (operand *, operand *,operand *);
80 void pic16_genMult16X16_16(operand *, operand *, operand *);
81 void pic16_genMult32X32_32(operand *, operand *, operand *);
82 pCode *pic16_AssembleLine(char *line, int peeps);
83 extern void pic16_printpBlock(FILE *of, pBlock *pb);
84 static asmop *newAsmop (short type);
85 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
86 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
87 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
88 static pCodeOp *pic16_popRegFromIdx(int rIdx);
89
90 //static int aopIdx (asmop *aop, int offset);
91
92 int pic16_labelOffset=0;
93 extern int pic16_debug_verbose;
94 #if !(USE_GENERIC_SIGNED_SHIFT)
95 static int optimized_for_speed = 0;
96 #endif
97 /*
98   hack hack
99
100 */
101
102 extern set *externs;
103
104 /* max_key keeps track of the largest label number used in 
105    a function. This is then used to adjust the label offset
106    for the next function.
107 */
108 static int max_key=0;
109 static int GpsuedoStkPtr=0;
110
111 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
112
113 unsigned int pic16aopLiteral (value *val, int offset);
114 const char *pic16_AopType(short type);
115 static iCode *ifxForOp ( operand *op, iCode *ic );
116
117 void pic16_pushpCodeOp(pCodeOp *pcop);
118 void pic16_poppCodeOp(pCodeOp *pcop);
119
120 static bool is_LitOp(operand *op);
121 static bool is_LitAOp(asmop *aop);
122
123
124 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
125
126 /* set the following macro to 1 to enable passing the
127  * first byte of functions parameters via WREG */
128 #define USE_WREG_IN_FUNC_PARAMS 0
129
130
131 /* this is the down and dirty file with all kinds of 
132    kludgy & hacky stuff. This is what it is all about
133    CODE GENERATION for a specific MCU . some of the
134    routines may be reusable, will have to see */
135
136 static char *zero = "#0x00";
137 static char *one  = "#0x01";
138 //static char *spname = "sp";
139
140
141 /*
142  * Function return value policy (MSB-->LSB):
143  *  8 bits      -> WREG
144  * 16 bits      -> PRODL:WREG
145  * 24 bits      -> PRODH:PRODL:WREG
146  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
147  * >32 bits     -> on stack, and FSR0 points to the beginning
148  *
149  */
150  
151
152 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
153 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
154 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
155 static char **fReturn = fReturnpic16;
156
157 static char *accUse[] = {"WREG"};
158
159 //static short rbank = -1;
160
161 static struct {
162     short r0Pushed;
163     short r1Pushed;
164     short fsr0Pushed;
165     short accInUse;
166     short inLine;
167     short debugLine;
168     short nRegsSaved;
169     short ipushRegs;
170     set *sendSet;
171     set *stackRegSet;
172     int usefastretfie;
173     bitVect *fregsUsed;                 /* registers used in function */
174     bitVect *sregsAlloc;
175     set *sregsAllocSet;                 /* registers used to store stack variables */
176     int stack_lat;                      /* stack offset latency */
177     int resDirect;
178     int useWreg;                        /* flag when WREG is used to pass function parameter */
179 } _G;
180
181 extern int pic16_ptrRegReq ;
182 extern int pic16_nRegs;
183 extern FILE *codeOutFile;
184 //static void saverbank (int, iCode *,bool);
185
186 static lineNode *lineHead = NULL;
187 static lineNode *lineCurr = NULL;
188
189 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
190 0xE0, 0xC0, 0x80, 0x00};
191 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
192 0x07, 0x03, 0x01, 0x00};
193
194 static  pBlock *pb;
195
196 /*-----------------------------------------------------------------*/
197 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
198 /*                 exponent of 2 is returned, otherwise -1 is      */
199 /*                 returned.                                       */
200 /* note that this is similar to the function `powof2' in SDCCsymt  */
201 /* if(n == 2^y)                                                    */
202 /*   return y;                                                     */
203 /* return -1;                                                      */
204 /*-----------------------------------------------------------------*/
205 int pic16_my_powof2 (unsigned long num)
206 {
207   if(num) {
208     if( (num & (num-1)) == 0) {
209       int nshifts = -1;
210       while(num) {
211         num>>=1;
212         nshifts++;
213       }
214       return nshifts;
215     }
216   }
217
218   return -1;
219 }
220
221 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
222 {
223   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
224                        line_no,
225                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
226                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
227                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
228                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
229                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
230                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
231                        ((result) ? AOP_SIZE(result) : 0));
232 }
233
234 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
235 {
236
237   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
238                        line_no,
239                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
240                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
241                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
242                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
243                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
244                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
245
246 }
247
248 void pic16_emitpcomment (char *fmt, ...)
249 {
250     va_list ap;
251     char lb[INITIAL_INLINEASM];  
252     unsigned char *lbp = (unsigned char *)lb;
253
254     va_start(ap,fmt);   
255
256     lb[0] = ';';
257     vsprintf(lb+1,fmt,ap);
258
259     while (isspace(*lbp)) lbp++;
260
261     if (lbp && *lbp) 
262         lineCurr = (lineCurr ?
263                     connectLine(lineCurr,newLineNode(lb)) :
264                     (lineHead = newLineNode(lb)));
265     lineCurr->isInline = _G.inLine;
266     lineCurr->isDebug  = _G.debugLine;
267
268     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
269     va_end(ap);
270
271 //      fprintf(stderr, "%s\n", lb);
272 }
273
274 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
275 {
276     va_list ap;
277     char lb[INITIAL_INLINEASM];  
278     unsigned char *lbp = (unsigned char *)lb;
279
280     if(!pic16_debug_verbose)
281       return;
282
283     va_start(ap,fmt);   
284
285     if (inst && *inst) {
286         if (fmt && *fmt)
287             sprintf(lb,"%s\t",inst);
288         else
289             sprintf(lb,"%s",inst);
290         vsprintf(lb+(strlen(lb)),fmt,ap);
291     }  else
292         vsprintf(lb,fmt,ap);
293
294     while (isspace(*lbp)) lbp++;
295
296     if (lbp && *lbp) 
297         lineCurr = (lineCurr ?
298                     connectLine(lineCurr,newLineNode(lb)) :
299                     (lineHead = newLineNode(lb)));
300     lineCurr->isInline = _G.inLine;
301     lineCurr->isDebug  = _G.debugLine;
302
303     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
304     va_end(ap);
305
306 //      fprintf(stderr, "%s\n", lb);
307 }
308
309
310
311 void pic16_emitpLabel(int key)
312 {
313   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
314 }
315
316 void pic16_emitpLabelFORCE(int key)
317 {
318   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
319 }
320
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322  * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
324 {
325
326   if(pcop)
327     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
328   else
329     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
330 }
331
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
333 {
334   if(pcop)
335     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
336   else
337     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
338 }
339   
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
341 {
342
343   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
344
345 }
346
347
348 #if 1
349 #define pic16_emitcode  DEBUGpic16_emitcode
350 #else
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple    */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
355 {
356     va_list ap;
357     char lb[INITIAL_INLINEASM];  
358     unsigned char *lbp = lb;
359
360     va_start(ap,fmt);   
361
362     if (inst && *inst) {
363         if (fmt && *fmt)
364             sprintf(lb,"%s\t",inst);
365         else
366             sprintf(lb,"%s",inst);
367         vsprintf(lb+(strlen(lb)),fmt,ap);
368     }  else
369         vsprintf(lb,fmt,ap);
370
371     while (isspace(*lbp)) lbp++;
372
373     if (lbp && *lbp) 
374         lineCurr = (lineCurr ?
375                     connectLine(lineCurr,newLineNode(lb)) :
376                     (lineHead = newLineNode(lb)));
377     lineCurr->isInline = _G.inLine;
378     lineCurr->isDebug  = _G.debugLine;
379
380 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
381
382 //    if(pic16_debug_verbose)
383 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
384
385     va_end(ap);
386 }
387 #endif
388
389
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location  */
392 /*   with a debugger symbol                                        */
393 /*-----------------------------------------------------------------*/
394 void
395 pic16_emitDebuggerSymbol (char * debugSym)
396 {
397   _G.debugLine = 1;
398   pic16_emitcode (";", "%s ==.", debugSym);
399   _G.debugLine = 0;
400 }
401
402
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
407 {
408 //    bool r0iu = FALSE , r1iu = FALSE;
409 //    bool r0ou = FALSE , r1ou = FALSE;
410     bool fsr0iu = FALSE, fsr0ou;
411     bool fsr2iu = FALSE, fsr2ou;
412     
413     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
414
415     
416     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
418     
419     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
421
422     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
425     }
426
427     if(!fsr0iu && !fsr0ou) {
428         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429         (*aopp)->type = AOP_FSR0;
430
431         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
432         
433       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
434     }
435
436 #if 0
437     /* no usage of FSR2 */
438     if(!fsr2iu && !fsr2ou) {
439         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440         (*aopp)->type = AOP_FSR2;
441
442       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
443     }
444 #endif
445         
446     /* now we know they both have usage */
447     /* if fsr0 not used in this instruction */
448     if (!fsr0iu) {
449         if (!_G.fsr0Pushed) {
450                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
452                 _G.fsr0Pushed++;
453         }
454
455         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456         (*aopp)->type = AOP_FSR0;
457
458 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
459
460       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
461     }
462         
463
464     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
465     assert( 0 );
466
467     return NULL;
468 #if 0
469     /* the logic: if r0 & r1 used in the instruction
470     then we are in trouble otherwise */
471
472     /* first check if r0 & r1 are used by this
473     instruction, in which case we are in trouble */
474     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
476     {
477         goto endOfWorld;      
478     }
479
480     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
482
483     /* if no usage of r0 then return it */
484     if (!r0iu && !r0ou) {
485         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486         (*aopp)->type = AOP_R0; 
487         
488         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
489     }
490
491     /* if no usage of r1 then return it */
492     if (!r1iu && !r1ou) {
493         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494         (*aopp)->type = AOP_R1;
495
496         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
497     }    
498
499     /* now we know they both have usage */
500     /* if r0 not used in this instruction */
501     if (!r0iu) {
502         /* push it if not already pushed */
503         if (!_G.r0Pushed) {
504           //pic16_emitcode ("push","%s",
505           //          pic16_regWithIdx(R0_IDX)->dname);
506             _G.r0Pushed++ ;
507         }
508         
509         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510         (*aopp)->type = AOP_R0;
511
512         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
513     }
514
515     /* if r1 not used then */
516
517     if (!r1iu) {
518         /* push it if not already pushed */
519         if (!_G.r1Pushed) {
520           //pic16_emitcode ("push","%s",
521           //          pic16_regWithIdx(R1_IDX)->dname);
522             _G.r1Pushed++ ;
523         }
524         
525         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526         (*aopp)->type = AOP_R1;
527         return pic16_regWithIdx(R1_IDX);
528     }
529
530 endOfWorld :
531     /* I said end of world but not quite end of world yet */
532     /* if this is a result then we can push it on the stack*/
533     if (result) {
534         (*aopp)->type = AOP_STK;    
535         return NULL;
536     }
537
538     /* other wise this is true end of the world */
539     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540            "getFreePtr should never reach here");
541     exit(0);
542 #endif
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp                                  */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
549 {
550     asmop *aop;
551
552     aop = Safe_calloc(1,sizeof(asmop));
553     aop->type = type;
554     return aop;
555 }
556
557 static void genSetDPTR(int n)
558 {
559     if (!n)
560     {
561         pic16_emitcode(";", "Select standard DPTR");
562         pic16_emitcode("mov", "dps, #0x00");
563     }
564     else
565     {
566         pic16_emitcode(";", "Select alternate DPTR");
567         pic16_emitcode("mov", "dps, #0x01");
568     }
569 }
570
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for  */
573 /*              generating code                                    */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
576 {
577   FENTRY2;
578   
579 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
580
581   if(!resIfx) 
582     return;
583
584
585   resIfx->condition = 1;    /* assume that the ifx is true */
586   resIfx->generated = 0;    /* indicate that the ifx has not been used */
587
588   if(!ifx) {
589     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
590
591 #if 1
592     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593                         __FUNCTION__,__LINE__,resIfx->lbl->key);
594 #endif
595
596   } else {
597     if(IC_TRUE(ifx)) {
598       resIfx->lbl = IC_TRUE(ifx);
599     } else {
600       resIfx->lbl = IC_FALSE(ifx);
601       resIfx->condition = 0;
602     }
603
604 #if 1
605     if(IC_TRUE(ifx)) 
606       DEBUGpic16_emitcode("; +++","ifx true is non-null");
607     else
608       DEBUGpic16_emitcode("; +++","ifx true is null");
609     if(IC_FALSE(ifx)) 
610       DEBUGpic16_emitcode("; +++","ifx false is non-null");
611     else
612       DEBUGpic16_emitcode("; +++","ifx false is null");
613 #endif
614   }
615
616   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
617
618 }
619 #if 0
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type               */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
624 {
625
626     return PTR_TYPE(SPEC_OCLS(etype));
627
628 }
629 #endif
630
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol                                   */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
635 {
636     symbol *sym=OP_SYMBOL(op);
637     asmop *aop;
638     memmap *space= SPEC_OCLS(sym->etype);
639
640     FENTRY2;
641     
642     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
643     
644 //    sym = OP_SYMBOL(op);
645
646     /* if already has one */
647     if (sym->aop) {
648             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
649         return sym->aop;
650     }
651
652 #if 0
653     /* if symbol was initially placed onStack then we must re-place it
654      * to direct memory, since pic16 does not have a specific stack */
655     if(sym->onStack) {
656         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
657     }
658 #endif
659
660
661 #if 0
662     if(sym->iaccess) {
663       if(space->paged) {
664         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
665
666         sym->aop = aop = newAsmop (AOP_PAGED);
667         aop->aopu.aop_dir = sym->rname ;
668         aop->size = getSize(sym->type);
669         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670         pic16_allocDirReg( IC_LEFT(ic) );
671         return aop;
672       }
673       assert( 0 );
674     }
675 #endif
676     
677 #if 1
678     /* assign depending on the storage class */
679     /* if it is on the stack or indirectly addressable */
680     /* space we need to assign either r0 or r1 to it   */    
681     if (sym->onStack)   // || sym->iaccess)
682     {
683       pCodeOp *pcop[4];
684       int i;
685       
686         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
688         
689         /* acquire a temporary register -- it is saved in function */
690
691         sym->aop = aop = newAsmop(AOP_STA);
692         aop->aopu.stk.stk = sym->stack;
693         aop->size = getSize(sym->type);
694
695
696         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
700           
701           for(i=0;i<aop->size;i++)
702             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
704         } else
705         if(1 && ic->op == SEND) {
706
707           /* if SEND do the send here */
708           _G.resDirect = 1;
709         } else {
710 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
711           for(i=0;i<aop->size;i++) {
712             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
713             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
714           }
715         }
716
717
718 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
719
720 #if 1
721         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
722
723         // we do not need to load the value if it is to be defined...
724         if (result) return aop;
725
726         if(_G.accInUse) {
727                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
728         }
729         
730         for(i=0;i<aop->size;i++) {
731
732           /* initialise for stack access via frame pointer */
733           // operands on stack are accessible via "{FRAME POINTER} + index" with index
734           // starting at 2 for arguments and growing from 0 downwards for
735           // local variables (index == 0 is not assigned so we add one here)
736           {
737             int soffs = sym->stack;
738             if (soffs <= 0) {
739               assert (soffs < 0);
740               soffs++;
741             } // if
742
743             if(1 && ic->op == SEND) {
744               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
745               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
746                     pic16_popCopyReg( pic16_frame_plusw ),
747                     pic16_popCopyReg(pic16_stack_postdec )));
748             } else {
749               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
750               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
752             }
753           }
754         }
755         
756         if(_G.accInUse) {
757                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
758         }
759         
760         return (aop);
761 #endif
762
763 #if 0
764         /* now assign the address of the variable to 
765         the pointer register */
766         if (aop->type != AOP_STK) {
767
768             if (sym->onStack) {
769                     if ( _G.accInUse )
770                         pic16_emitcode("push","acc");
771
772                     pic16_emitcode("mov","a,_bp");
773                     pic16_emitcode("add","a,#0x%02x",
774                              ((sym->stack < 0) ?
775                               ((char)(sym->stack - _G.nRegsSaved )) :
776                               ((char)sym->stack)) & 0xff);
777                     pic16_emitcode("mov","%s,a",
778                              aop->aopu.aop_ptr->name);
779
780                     if ( _G.accInUse )
781                         pic16_emitcode("pop","acc");
782             } else
783                 pic16_emitcode("mov","%s,#%s",
784                          aop->aopu.aop_ptr->name,
785                          sym->rname);
786             aop->paged = space->paged;
787         } else
788             aop->aopu.aop_stk = sym->stack;
789         return aop;
790 #endif
791
792     }
793 #endif
794
795 #if 0
796     if (sym->onStack && options.stack10bit)
797     {
798         /* It's on the 10 bit stack, which is located in
799          * far data space.
800          */
801          
802       //DEBUGpic16_emitcode(";","%d",__LINE__);
803
804         if ( _G.accInUse )
805                 pic16_emitcode("push","acc");
806
807         pic16_emitcode("mov","a,_bp");
808         pic16_emitcode("add","a,#0x%02x",
809                  ((sym->stack < 0) ?
810                    ((char)(sym->stack - _G.nRegsSaved )) :
811                    ((char)sym->stack)) & 0xff);
812         
813         genSetDPTR(1);
814         pic16_emitcode ("mov","dpx1,#0x40");
815         pic16_emitcode ("mov","dph1,#0x00");
816         pic16_emitcode ("mov","dpl1, a");
817         genSetDPTR(0);
818         
819         if ( _G.accInUse )
820             pic16_emitcode("pop","acc");
821             
822         sym->aop = aop = newAsmop(AOP_DPTR2);
823         aop->size = getSize(sym->type); 
824         return aop;
825     }
826 #endif
827
828 #if 1
829     /* special case for a function */
830     if (IS_FUNC(sym->type)) {   
831         sym->aop = aop = newAsmop(AOP_PCODE);
832         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
833         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
834         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
835         PCOI(aop->aopu.pcop)->index = 0;
836         aop->size = FPTRSIZE; 
837         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
838         return aop;
839     }
840 #endif
841
842
843
844     //DEBUGpic16_emitcode(";","%d",__LINE__);
845     /* if in bit space */
846     if (IN_BITSPACE(space)) {
847         sym->aop = aop = newAsmop (AOP_CRY);
848         aop->aopu.aop_dir = sym->rname ;
849         aop->size = getSize(sym->type);
850         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851         return aop;
852     }
853     /* if it is in direct space */
854     if (IN_DIRSPACE(space)) {
855                 if(!strcmp(sym->rname, "_WREG")) {
856                         sym->aop = aop = newAsmop (AOP_ACC);
857                         aop->size = getSize(sym->type);         /* should always be 1 */
858                         assert(aop->size == 1);
859                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
860                         return (aop);
861                 } else {
862                         sym->aop = aop = newAsmop (AOP_DIR);
863                 aop->aopu.aop_dir = sym->rname ;
864             aop->size = getSize(sym->type);
865                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
866                         pic16_allocDirReg( IC_LEFT(ic) );
867                         return (aop);
868                 }
869         }
870
871     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
872         sym->aop = aop = newAsmop (AOP_DIR);
873         aop->aopu.aop_dir = sym->rname ;
874         aop->size = getSize(sym->type);
875         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
876         pic16_allocDirReg( IC_LEFT(ic) );
877         return aop;
878     }
879
880
881     /* only remaining is far space */
882     sym->aop = aop = newAsmop(AOP_PCODE);
883
884 /* change the next if to 1 to revert to good old immediate code */
885         if(IN_CODESPACE(space)) {
886                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
887                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
888                 PCOI(aop->aopu.pcop)->index = 0;
889         } else {
890                 /* try to allocate via direct register */
891                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
892 //              aop->size = getSize( sym->type );
893         }
894
895         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
896                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
897
898 #if 0
899         if(!pic16_allocDirReg (IC_LEFT(ic)))
900                 return NULL;
901 #endif
902
903         if(IN_DIRSPACE( space ))
904                 aop->size = PTRSIZE;
905         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
906                 aop->size = FPTRSIZE;
907         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
908         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
909         else if(sym->onStack) {
910                 aop->size = PTRSIZE;
911         } else {
912           if(SPEC_SCLS(sym->etype) == S_PDATA) {
913             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
914             aop->size = FPTRSIZE;
915           } else
916                 assert( 0 );
917         }
918
919     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
920
921     /* if it is in code space */
922     if (IN_CODESPACE(space))
923         aop->code = 1;
924
925     return aop;     
926 }
927
928 /*-----------------------------------------------------------------*/
929 /* aopForRemat - rematerialzes an object                           */
930 /*-----------------------------------------------------------------*/
931 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
932 {
933   symbol *sym = OP_SYMBOL(op);
934   operand *refop;
935   iCode *ic = NULL, *oldic;
936   asmop *aop = newAsmop(AOP_PCODE);
937   int val = 0;
938   int offset = 0;
939   int viaimmd=0;
940
941     FENTRY2;
942     
943         ic = sym->rematiCode;
944
945         if(IS_OP_POINTER(op)) {
946                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
947         }
948
949 //    if(!result)               /* fixme-vr */
950         for (;;) {
951                 oldic = ic;
952
953 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
954         
955                 if (ic->op == '+') {
956                         val += (int) operandLitValue(IC_RIGHT(ic));
957                 } else if (ic->op == '-') {
958                         val -= (int) operandLitValue(IC_RIGHT(ic));
959                 } else
960                         break;
961                 
962                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
963         }
964
965         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
966         refop = IC_LEFT(ic);
967
968         if(!op->isaddr)viaimmd++; else viaimmd=0;
969                 
970 /* set the following if to 1 to revert to good old immediate code */
971         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
972                 || viaimmd) {
973
974                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
975
976                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
977
978 #if 0
979                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
980 #else
981                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
982 #endif
983
984                 PCOI(aop->aopu.pcop)->index = val;
985                 
986                 aop->size = getSize( sym->type );
987         } else {
988                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
989
990                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
991                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
992
993                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
994         }
995
996
997         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
998                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
999 #if 0
1000                 val, IS_PTR_CONST(operandType(op)));
1001 #else
1002                 val, IS_CODEPTR(operandType(op)));
1003 #endif
1004
1005 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1006
1007         pic16_allocDirReg (IC_LEFT(ic));
1008
1009         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1010                 aop->code = 1;
1011
1012   return aop;        
1013 }
1014
1015 #if 0
1016 static int aopIdx (asmop *aop, int offset)
1017 {
1018   if(!aop)
1019     return -1;
1020
1021   if(aop->type !=  AOP_REG)
1022     return -2;
1023         
1024   return aop->aopu.aop_reg[offset]->rIdx;
1025
1026 }
1027 #endif
1028
1029 /*-----------------------------------------------------------------*/
1030 /* regsInCommon - two operands have some registers in common       */
1031 /*-----------------------------------------------------------------*/
1032 static bool regsInCommon (operand *op1, operand *op2)
1033 {
1034     symbol *sym1, *sym2;
1035     int i;
1036
1037     /* if they have registers in common */
1038     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1039         return FALSE ;
1040
1041     sym1 = OP_SYMBOL(op1);
1042     sym2 = OP_SYMBOL(op2);
1043
1044     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1045         return FALSE ;
1046
1047     for (i = 0 ; i < sym1->nRegs ; i++) {
1048         int j;
1049         if (!sym1->regs[i])
1050             continue ;
1051
1052         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1053             if (!sym2->regs[j])
1054                 continue ;
1055
1056             if (sym2->regs[j] == sym1->regs[i])
1057                 return TRUE ;
1058         }
1059     }
1060
1061     return FALSE ;
1062 }
1063
1064 /*-----------------------------------------------------------------*/
1065 /* operandsEqu - equivalent                                        */
1066 /*-----------------------------------------------------------------*/
1067 static bool operandsEqu ( operand *op1, operand *op2)
1068 {
1069     symbol *sym1, *sym2;
1070
1071     /* if they not symbols */
1072     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1073         return FALSE;
1074
1075     sym1 = OP_SYMBOL(op1);
1076     sym2 = OP_SYMBOL(op2);
1077
1078     /* if both are itemps & one is spilt
1079        and the other is not then false */
1080     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1081         sym1->isspilt != sym2->isspilt )
1082         return FALSE ;
1083
1084     /* if they are the same */
1085     if (sym1 == sym2)
1086         return TRUE ;
1087
1088     if (sym1->rname[0] && sym2->rname[0]
1089         && strcmp (sym1->rname, sym2->rname) == 0)
1090         return TRUE;
1091
1092
1093     /* if left is a tmp & right is not */
1094     if (IS_ITEMP(op1)  && 
1095         !IS_ITEMP(op2) &&
1096         sym1->isspilt  &&
1097         (sym1->usl.spillLoc == sym2))
1098         return TRUE;
1099
1100     if (IS_ITEMP(op2)  && 
1101         !IS_ITEMP(op1) &&
1102         sym2->isspilt  &&
1103         sym1->level > 0 &&
1104         (sym2->usl.spillLoc == sym1))
1105         return TRUE ;
1106
1107     return FALSE ;
1108 }
1109
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_sameRegs - two asmops have the same registers                   */
1112 /*-----------------------------------------------------------------*/
1113 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1114 {
1115     int i;
1116
1117     if (aop1 == aop2)
1118         return TRUE ;
1119
1120     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1121                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1122
1123     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1124
1125     if (aop1->type != AOP_REG ||
1126         aop2->type != AOP_REG )
1127         return FALSE ;
1128
1129     /* This is a bit too restrictive if one is a subset of the other...
1130     if (aop1->size != aop2->size )
1131         return FALSE ;
1132     */
1133
1134     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1135 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1136
1137 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1138         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1139             return FALSE ;
1140     }
1141
1142     return TRUE ;
1143 }
1144
1145 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1146 {
1147     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1148                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1149
1150     if(aop1 == aop2)return TRUE;
1151     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1152       
1153       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1154     
1155   return TRUE;
1156 }
1157
1158
1159 /*-----------------------------------------------------------------*/
1160 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1161 /*-----------------------------------------------------------------*/
1162 void pic16_aopOp (operand *op, iCode *ic, bool result)
1163 {
1164     asmop *aop;
1165     symbol *sym;
1166     int i;
1167
1168     if (!op)
1169         return ;
1170
1171     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1172
1173     /* if this a literal */
1174     if (IS_OP_LITERAL(op)) {
1175         op->aop = aop = newAsmop(AOP_LIT);
1176         aop->aopu.aop_lit = op->operand.valOperand;
1177         aop->size = getSize(operandType(op));
1178         return;
1179     }
1180
1181     {
1182       sym_link *type = operandType(op);
1183 #if 0
1184       if(IS_PTR_CONST(type))
1185 #else
1186       if(IS_CODEPTR(type))
1187 #endif
1188         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1189     }
1190
1191     /* if already has a asmop then continue */
1192     if (op->aop)
1193         return ;
1194
1195     /* if the underlying symbol has a aop */
1196     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1197       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1198         op->aop = OP_SYMBOL(op)->aop;
1199         return;
1200     }
1201
1202     /* if this is a true symbol */
1203     if (IS_TRUE_SYMOP(op)) {    
1204         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1205       op->aop = aopForSym(ic, op, result);
1206       return ;
1207     }
1208
1209     /* this is a temporary : this has
1210     only four choices :
1211     a) register
1212     b) spillocation
1213     c) rematerialize 
1214     d) conditional   
1215     e) can be a return use only */
1216
1217     sym = OP_SYMBOL(op);
1218
1219     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1220     /* if the type is a conditional */
1221     if (sym->regType == REG_CND) {
1222         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1223         aop->size = 0;
1224         return;
1225     }
1226
1227     /* if it is spilt then two situations
1228     a) is rematerialize 
1229     b) has a spill location */
1230     if (sym->isspilt || sym->nRegs == 0) {
1231
1232 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1233       DEBUGpic16_emitcode(";","%d",__LINE__);
1234         /* rematerialize it NOW */
1235         if (sym->remat) {
1236
1237             sym->aop = op->aop = aop = aopForRemat (op, result);
1238 //            aop->size = getSize(sym->type);
1239 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1240             return;
1241         }
1242
1243 #if 1
1244         if (sym->accuse) {
1245             int i;
1246             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1247             aop->size = getSize(sym->type);
1248             for ( i = 0 ; i < 1 ; i++ ) {
1249                 aop->aopu.aop_str[i] = accUse[i];
1250 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1251             }
1252             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1253             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1254             return;  
1255         }
1256 #endif
1257
1258 #if 1
1259         if (sym->ruonly) {
1260           /*
1261           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1262           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1263           //pic16_allocDirReg (IC_LEFT(ic));
1264           aop->size = getSize(sym->type);
1265           */
1266
1267           unsigned i;
1268
1269           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1270           aop->size = getSize(sym->type);
1271           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1272             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1273
1274           DEBUGpic16_emitcode(";","%d",__LINE__);
1275           return;
1276         }
1277 #endif
1278         /* else spill location  */
1279         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1280             /* force a new aop if sizes differ */
1281             sym->usl.spillLoc->aop = NULL;
1282         }
1283
1284 #if 0
1285         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1286                             __FUNCTION__,__LINE__,
1287                             sym->usl.spillLoc->rname,
1288                             sym->rname, sym->usl.spillLoc->offset);
1289 #endif
1290
1291         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1294           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1295                                                   getSize(sym->type), 
1296                                                   sym->usl.spillLoc->offset, op);
1297         } else if (getSize(sym->type) <= 1) {
1298           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1299           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300           assert (getSize(sym->type) <= 1);
1301           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1303         } else {
1304           /* We need some kind of dummy area for getSize(sym->type) byte,
1305            * use WREG for all storage locations.
1306            * XXX: This only works if we are implementing a `dummy read',
1307            *      the stored value will not be retrievable...
1308            *      See #1503234 for a case requiring this. */
1309           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1310           aop->size = getSize(sym->type);
1311           for ( i = 0 ; i < aop->size ;i++)
1312             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1313         }
1314         aop->size = getSize(sym->type);
1315
1316         return;
1317     }
1318
1319     {
1320       sym_link *type = operandType(op);
1321 #if 0
1322       if(IS_PTR_CONST(type)) 
1323 #else
1324       if(IS_CODEPTR(type)) 
1325 #endif
1326         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1327     }
1328
1329     /* must be in a register */
1330     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1331     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1332     aop->size = sym->nRegs;
1333     for ( i = 0 ; i < sym->nRegs ;i++)
1334         aop->aopu.aop_reg[i] = sym->regs[i];
1335 }
1336
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_freeAsmop - free up the asmop given to an operand               */
1339 /*----------------------------------------------------------------*/
1340 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1341 {   
1342     asmop *aop ;
1343
1344     if (!op)
1345         aop = aaop;
1346     else 
1347         aop = op->aop;
1348
1349     if (!aop)
1350         return ;
1351
1352     if (aop->freed)
1353         goto dealloc; 
1354
1355     aop->freed = 1;
1356
1357     /* depending on the asmop type only three cases need work AOP_RO
1358        , AOP_R1 && AOP_STK */
1359 #if 1
1360     switch (aop->type) {
1361         case AOP_FSR0 :
1362             if (_G.fsr0Pushed ) {
1363                 if (pop) {
1364                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1365                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1366 //                    pic16_emitcode ("pop","ar0");
1367                     _G.fsr0Pushed--;
1368                 }
1369             }
1370             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1371             break;
1372
1373         case AOP_FSR2 :
1374             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1375             break;
1376
1377         case AOP_R0 :
1378             if (_G.r0Pushed ) {
1379                 if (pop) {
1380                     pic16_emitcode ("pop","ar0");     
1381                     _G.r0Pushed--;
1382                 }
1383             }
1384             bitVectUnSetBit(ic->rUsed,R0_IDX);
1385             break;
1386
1387         case AOP_R1 :
1388             if (_G.r1Pushed ) {
1389                 if (pop) {
1390                     pic16_emitcode ("pop","ar1");
1391                     _G.r1Pushed--;
1392                 }
1393             }
1394             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1395             break;
1396
1397         case AOP_STA:
1398           {
1399             int i;
1400
1401               /* we must store the result on stack */
1402               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1403                 // operands on stack are accessible via "FSR2 + index" with index
1404                 // starting at 2 for arguments and growing from 0 downwards for
1405                 // local variables (index == 0 is not assigned so we add one here)
1406                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1407                 if (soffs <= 0) {
1408                   assert (soffs < 0);
1409                   soffs++;
1410                 } // if
1411                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1412                 for(i=0;i<aop->size;i++) {
1413                   /* initialise for stack access via frame pointer */
1414                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1415                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1416                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1417                 }
1418         
1419                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1420               }
1421
1422               if(!_G.resDirect) {
1423                 for(i=0;i<aop->size;i++) {
1424                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1425
1426                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1427                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1428 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1429                   }
1430                 }
1431                 
1432                 {
1433                   regs *sr;
1434                   
1435                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1436                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1437                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1438                       deleteSetItem( &_G.sregsAllocSet, sr );
1439                     }
1440                 }
1441               }
1442               _G.resDirect = 0;
1443           }
1444           break;
1445 #if 0
1446         case AOP_STK :
1447         {
1448             int sz = aop->size;    
1449             int stk = aop->aopu.aop_stk + aop->size;
1450             bitVectUnSetBit(ic->rUsed,R0_IDX);
1451             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1452
1453             getFreePtr(ic,&aop,FALSE);
1454             
1455             if (options.stack10bit)
1456             {
1457                 /* I'm not sure what to do here yet... */
1458                 /* #STUB */
1459                 fprintf(stderr, 
1460                         "*** Warning: probably generating bad code for "
1461                         "10 bit stack mode.\n");
1462             }
1463             
1464             if (stk) {
1465                 pic16_emitcode ("mov","a,_bp");
1466                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1467                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1468             } else {
1469                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1470             }
1471
1472             while (sz--) {
1473                 pic16_emitcode("pop","acc");
1474                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1475                 if (!sz) break;
1476                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1477             }
1478             op->aop = aop;
1479             pic16_freeAsmop(op,NULL,ic,TRUE);
1480             if (_G.r0Pushed) {
1481                 pic16_emitcode("pop","ar0");
1482                 _G.r0Pushed--;
1483             }
1484
1485             if (_G.r1Pushed) {
1486                 pic16_emitcode("pop","ar1");
1487                 _G.r1Pushed--;
1488             }       
1489         }
1490 #endif
1491
1492     }
1493 #endif
1494
1495 dealloc:
1496     /* all other cases just dealloc */
1497     if (op ) {
1498         op->aop = NULL;
1499         if (IS_SYMOP(op)) {
1500             OP_SYMBOL(op)->aop = NULL;    
1501             /* if the symbol has a spill */
1502             if (SPIL_LOC(op))
1503                 SPIL_LOC(op)->aop = NULL;
1504         }
1505     }
1506 }
1507
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_aopGet - for fetching value of the aop                          */
1510 /*-----------------------------------------------------------------*/
1511 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1512 {
1513     char *s = buffer ;
1514     char *rs;
1515
1516     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1517
1518     /* offset is greater than size then zero */
1519     if (offset > (aop->size - 1) &&
1520         aop->type != AOP_LIT)
1521         return zero;
1522
1523     /* depending on type */
1524     switch (aop->type) {
1525
1526     case AOP_FSR0:
1527     case AOP_FSR2:
1528       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1529       rs = Safe_calloc(1, strlen(s)+1);
1530       strcpy(rs, s);
1531       return (rs);
1532       
1533 #if 0
1534       /* if we need to increment it */
1535       while (offset > aop->coff)
1536         {
1537           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1538           aop->coff++;
1539         }
1540
1541       while (offset < aop->coff)
1542         {
1543           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1544           aop->coff--;
1545         }
1546       aop->coff = offset;
1547       if (aop->paged)
1548         {
1549           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1550           return (dname ? "acc" : "a");
1551         }
1552       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1553       rs = Safe_calloc (1, strlen (s) + 1);
1554       strcpy (rs, s);
1555       return rs;
1556 #endif
1557
1558         
1559     case AOP_IMMD:
1560         if (bit16) 
1561             sprintf (s,"%s",aop->aopu.aop_immd);
1562         else
1563             if (offset) 
1564                 sprintf(s,"(%s >> %d)",
1565                         aop->aopu.aop_immd,
1566                         offset*8);
1567             else
1568                 sprintf(s,"%s",
1569                         aop->aopu.aop_immd);
1570         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1571         rs = Safe_calloc(1,strlen(s)+1);
1572         strcpy(rs,s);   
1573         return rs;
1574         
1575     case AOP_DIR:
1576       if (offset) {
1577         sprintf(s,"(%s + %d)",
1578                 aop->aopu.aop_dir,
1579                 offset);
1580         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1581       } else
1582             sprintf(s,"%s",aop->aopu.aop_dir);
1583         rs = Safe_calloc(1,strlen(s)+1);
1584         strcpy(rs,s);   
1585         return rs;
1586         
1587     case AOP_REG:
1588       return aop->aopu.aop_reg[offset]->name;
1589         
1590     case AOP_CRY:
1591       return aop->aopu.aop_dir;
1592         
1593     case AOP_ACC:
1594         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1595 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1596 //        assert( 0 );
1597 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1598         rs = Safe_strdup("WREG");
1599         return (rs);
1600
1601     case AOP_LIT:
1602         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1603         rs = Safe_calloc(1,strlen(s)+1);
1604         strcpy(rs,s);   
1605         return rs;
1606         
1607     case AOP_STR:
1608         aop->coff = offset ;
1609
1610 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1611 //          dname)
1612 //          return "acc";
1613         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1614           aop->type = AOP_ACC;
1615           return Safe_strdup("_WREG");
1616         }
1617         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1618         
1619         return aop->aopu.aop_str[offset];
1620         
1621     case AOP_PCODE:
1622       {
1623         pCodeOp *pcop = aop->aopu.pcop;
1624         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1625         if(pcop->name) {
1626           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1627           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1628           if (offset) {
1629             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1630           } else {
1631             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1632           }
1633         } else
1634           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1635
1636       }
1637       rs = Safe_calloc(1,strlen(s)+1);
1638       strcpy(rs,s);   
1639       return rs;
1640
1641 #if 0
1642     case AOP_PAGED:
1643       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644       if (offset) {
1645         sprintf(s,"(%s + %d)",
1646                 aop->aopu.aop_dir,
1647                 offset);
1648       } else
1649             sprintf(s,"%s",aop->aopu.aop_dir);
1650       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651       rs = Safe_calloc(1,strlen(s)+1);
1652       strcpy(rs,s);   
1653       return rs;
1654 #endif
1655
1656     case AOP_STA:
1657         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1658         return (rs);
1659         
1660     case AOP_STK:
1661 //        pCodeOp *pcop = aop->aop
1662         break;
1663
1664     }
1665
1666     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1667     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1668            "aopget got unsupported aop->type");
1669     exit(0);
1670 }
1671
1672
1673
1674 /* lock has the following meaning: When allocating temporary registers
1675  * for stack variables storage, the value of the temporary register is
1676  * saved on stack. Its value is restored at the end. This procedure is
1677  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1678  * a possibility that before a call to pic16_aopOp, a temporary register
1679  * is allocated for a while and it is freed after some time, this will
1680  * mess the stack and values will not be restored properly. So use lock=1
1681  * to allocate temporary registers used internally by the programmer, and
1682  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1683  * to inform the compiler developer about a possible bug. This is an internal
1684  * feature for developing the compiler -- VR */
1685  
1686 int _TempReg_lock = 0;
1687 /*-----------------------------------------------------------------*/
1688 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1689 /*-----------------------------------------------------------------*/
1690 pCodeOp *pic16_popGetTempReg(int lock)
1691 {
1692   pCodeOp *pcop=NULL;
1693   symbol *cfunc;
1694
1695 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1696     if(_TempReg_lock) {
1697 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1698     }
1699     
1700     _TempReg_lock += lock;
1701     
1702     cfunc = currFunc;
1703     currFunc = NULL;
1704
1705 #if 0
1706         {
1707           regs *rr;
1708           int i;
1709
1710                 /* this code might seem better but it does the *same* job with
1711                  * the old code, it all depends on ralloc.c to get a free/unused
1712                  * register */
1713          
1714                 i=0;
1715                 while(i < pic16_nRegs) {
1716                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1717                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1718                         if((!rr || (rr && rr->isFree))
1719                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1720                                 pcop = pic16_newpCodeOpReg( i );
1721                                 PCOR(pcop)->r->wasUsed = 1;
1722                                 PCOR(pcop)->r->isFree = 0;
1723                                 break;
1724                         }
1725                         i++;
1726                 }
1727
1728                 if(pcop) {
1729                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1730                 }
1731         }
1732 #else
1733     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1734     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1735       PCOR(pcop)->r->wasUsed=1;
1736       PCOR(pcop)->r->isFree=0;
1737
1738       /* push value on stack */
1739       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1740     }
1741 #endif
1742
1743     currFunc = cfunc;
1744
1745   return pcop;
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1750 /*                           is not part of f, but don't save if   */
1751 /*                           inside v                              */
1752 /*-----------------------------------------------------------------*/
1753 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1754 {
1755   pCodeOp *pcop=NULL;
1756   symbol *cfunc;
1757   int i;
1758
1759 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1760
1761     if(_TempReg_lock) {
1762 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1763     }
1764
1765     _TempReg_lock += lock;
1766
1767     cfunc = currFunc;
1768     currFunc = NULL;
1769
1770     i = bitVectFirstBit(f);
1771     while(i < 128) {
1772
1773       /* bypass registers that are used by function */
1774       if(!bitVectBitValue(f, i)) {
1775       
1776         /* bypass registers that are already allocated for stack access */
1777         if(!bitVectBitValue(v, i))  {
1778         
1779 //          debugf("getting register rIdx = %d\n", i);
1780           /* ok, get the operand */
1781           pcop = pic16_newpCodeOpReg( i );
1782     
1783           /* should never by NULL */
1784           assert( pcop != NULL );
1785
1786           
1787           /* sanity check */
1788           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1789             int found=0;
1790             
1791               PCOR(pcop)->r->wasUsed=1;
1792               PCOR(pcop)->r->isFree=0;
1793
1794
1795               {
1796                 regs *sr;
1797               
1798                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1799
1800                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1801                       /* already used in previous steps, break */
1802                       found=1;          
1803                       break;
1804                     }
1805                   }
1806               }
1807
1808               /* caller takes care of the following */
1809 //              bitVectSetBit(v, i);
1810
1811               if(!found) {
1812                 /* push value on stack */
1813                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1814                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1815               }
1816           
1817             break;
1818           }
1819         }
1820       }
1821       i++;
1822     }
1823
1824     currFunc = cfunc;
1825
1826   return pcop;
1827 }
1828
1829
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1832 /*-----------------------------------------------------------------*/
1833 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1834 {
1835   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1836
1837   _TempReg_lock -= lock;
1838
1839   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1840     PCOR(pcop)->r->isFree = 1;
1841
1842     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1843   }
1844 }
1845 /*-----------------------------------------------------------------*/
1846 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1847 /*-----------------------------------------------------------------*/
1848 pCodeOp *pic16_popGetLabel(int key)
1849 {
1850
1851   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1852
1853   if(key>max_key)
1854     max_key = key;
1855
1856   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* pic16_popCopyReg - copy a pcode operator                              */
1861 /*-----------------------------------------------------------------*/
1862 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1863 {
1864   pCodeOpReg *pcor;
1865
1866   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1867   memcpy (pcor, pc, sizeof (pCodeOpReg));
1868   pcor->r->wasUsed = 1;
1869   
1870   //pcor->pcop.type = pc->pcop.type;
1871   if(pc->pcop.name) {
1872     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1873       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1874   } else
1875     pcor->pcop.name = NULL;
1876
1877   //pcor->r = pc->r;
1878   //pcor->rIdx = pc->rIdx;
1879   //pcor->r->wasUsed=1;
1880   //pcor->instance = pc->instance;
1881
1882 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1883
1884   return PCOP(pcor);
1885 }
1886
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetLit(int lit)
1891 {
1892   return pic16_newpCodeOpLit(lit);
1893 }
1894
1895 /* Allow for 12 bit literals (LFSR x, <here!>). */
1896 pCodeOp *pic16_popGetLit12(int lit)
1897 {
1898   return pic16_newpCodeOpLit12(lit);
1899 }
1900
1901 /*-----------------------------------------------------------------*/
1902 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1903 /*-----------------------------------------------------------------*/
1904 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1905 {
1906   return pic16_newpCodeOpLit2(lit, arg2);
1907 }
1908
1909
1910 /*-----------------------------------------------------------------*/
1911 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1912 /*-----------------------------------------------------------------*/
1913 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1914 {
1915   return pic16_newpCodeOpImmd(name, offset,index, 0);
1916 }
1917
1918
1919 /*-----------------------------------------------------------------*/
1920 /* pic16_popGet - asm operator to pcode operator conversion              */
1921 /*-----------------------------------------------------------------*/
1922 pCodeOp *pic16_popGetWithString(char *str)
1923 {
1924   pCodeOp *pcop;
1925
1926
1927   if(!str) {
1928     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1929     exit (1);
1930   }
1931
1932   pcop = pic16_newpCodeOp(str,PO_STR);
1933
1934   return pcop;
1935 }
1936
1937 /*-----------------------------------------------------------------*/
1938 /* pic16_popRegFromString -                                        */
1939 /*-----------------------------------------------------------------*/
1940 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1941 {
1942
1943   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1944   pcop->type = PO_DIR;
1945
1946   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1947   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1948
1949   if(!str)
1950     str = "BAD_STRING";
1951
1952   pcop->name = Safe_calloc(1,strlen(str)+1);
1953   strcpy(pcop->name,str);
1954
1955   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1956
1957   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1958 //  PCOR(pcop)->r->wasUsed = 1;
1959
1960   /* make sure that register doesn't exist,
1961    * and operand isn't NULL
1962    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1963   if((PCOR(pcop)->r == NULL) 
1964     && (op)
1965     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1966 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1967 //              __FUNCTION__, __LINE__, str, size, offset);
1968
1969     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1970     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1971
1972   }
1973   PCOR(pcop)->instance = offset;
1974
1975   return pcop;
1976 }
1977
1978 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1979 {
1980   pCodeOp *pcop;
1981
1982 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1983 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1984         
1985         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1986         PCOR(pcop)->rIdx = rIdx;
1987         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1988         if(!PCOR(pcop)->r)
1989                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1990                 
1991         PCOR(pcop)->r->isFree = 0;
1992         PCOR(pcop)->r->wasUsed = 1;
1993
1994         pcop->type = PCOR(pcop)->r->pc_type;
1995
1996   return pcop;
1997 }
1998
1999 /*---------------------------------------------------------------------------------*/
2000 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2001 /*                 VR 030601                                                       */
2002 /*---------------------------------------------------------------------------------*/
2003 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2004 {
2005   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2006         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2007   return PCOP(pcop2);
2008 }
2009
2010
2011
2012 /*--------------------------------------------------------------------------------.-*/
2013 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2014 /*                  VR 030601 , adapted by Hans Dorn                                */
2015 /*--------------------------------------------------------------------------------.-*/
2016 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2017 {
2018   pCodeOp2 *pcop2;
2019   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2020   return PCOP(pcop2);
2021 }
2022
2023 /*---------------------------------------------------------------------------------*/
2024 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2025 /*                     movff instruction                                           */
2026 /*---------------------------------------------------------------------------------*/
2027 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2028 {
2029   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2030         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2031
2032   return PCOP(pcop2);
2033 }
2034
2035
2036 /*-----------------------------------------------------------------*/
2037 /* pic16_popGet - asm operator to pcode operator conversion              */
2038 /*-----------------------------------------------------------------*/
2039 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2040 {
2041 //  char *s = buffer ;
2042 //  char *rs;
2043   pCodeOp *pcop;
2044
2045     FENTRY2;
2046     
2047       /* offset is greater than size then zero */
2048
2049 //    if (offset > (aop->size - 1) &&
2050 //        aop->type != AOP_LIT)
2051 //      return NULL;  //zero;
2052
2053     /* depending on type */
2054     switch (aop->type) {
2055                 case AOP_R0:
2056                 case AOP_R1:
2057                 case AOP_DPTR:
2058                 case AOP_DPTR2:
2059                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2060                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2061                         assert( 0 );
2062                         return NULL;
2063
2064                 case AOP_FSR0:
2065                 case AOP_FSR2:
2066                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2067                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2068                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2069                         PCOR(pcop)->r->wasUsed = 1;
2070                         PCOR(pcop)->r->isFree = 0;
2071       
2072                         PCOR(pcop)->instance = offset;
2073                         pcop->type = PCOR(pcop)->r->pc_type;
2074                         return (pcop);
2075
2076                 case AOP_IMMD:
2077                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2078                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2079
2080                 case AOP_STA:
2081                         /* pCodeOp is already allocated from aopForSym */
2082                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2083                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2084                         return (pcop);
2085       
2086                 case AOP_ACC:
2087                         {
2088                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2089
2090                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2091
2092                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2093         
2094                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2095                                 PCOR(pcop)->rIdx = rIdx;
2096                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2097                                 PCOR(pcop)->r->wasUsed=1;
2098                                 PCOR(pcop)->r->isFree=0;
2099
2100                                 PCOR(pcop)->instance = offset;
2101                                 pcop->type = PCOR(pcop)->r->pc_type;
2102 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2103                                 return pcop;
2104
2105
2106 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2107 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2108
2109 //      assert( 0 );
2110                         }
2111         
2112     case AOP_DIR:
2113       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2114       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2115         
2116 #if 0
2117     case AOP_PAGED:
2118       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2119       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2120 #endif
2121
2122     case AOP_REG:
2123       {
2124         int rIdx;
2125
2126 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2127 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2128         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2129
2130         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2131         
2132         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2133 //      pcop->type = PO_GPR_REGISTER;
2134         PCOR(pcop)->rIdx = rIdx;
2135         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2136         PCOR(pcop)->r->wasUsed=1;
2137         PCOR(pcop)->r->isFree=0;
2138
2139         PCOR(pcop)->instance = offset;
2140         pcop->type = PCOR(pcop)->r->pc_type;
2141         
2142         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2143 //      rs = aop->aopu.aop_reg[offset]->name;
2144 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2145         return pcop;
2146       }
2147
2148     case AOP_CRY:
2149         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2150
2151       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2152       PCOR(pcop)->instance = offset;
2153       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2154       //if(PCOR(pcop)->r == NULL)
2155       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2156       return pcop;
2157         
2158     case AOP_LIT:
2159         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2160       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2161
2162     case AOP_STR:
2163       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2164       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2165
2166       /*
2167       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2168       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2169       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2170       pcop->type = PCOR(pcop)->r->pc_type;
2171       pcop->name = PCOR(pcop)->r->name;
2172
2173       return pcop;
2174       */
2175
2176     case AOP_PCODE:
2177       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2178                           __LINE__, 
2179                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2180       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2181       switch( aop->aopu.pcop->type ) {
2182         case PO_DIR: PCOR(pcop)->instance += offset; break;
2183         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2184         case PO_WREG:
2185             assert (offset==0);
2186             break;
2187         default:
2188           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2189           assert( 0 );  /* should never reach here */;
2190       }
2191       return pcop;
2192     }
2193
2194     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2195            "pic16_popGet got unsupported aop->type");
2196     exit(0);
2197 }
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_aopPut - puts a string for a aop                                */
2200 /*-----------------------------------------------------------------*/
2201 void pic16_aopPut (asmop *aop, char *s, int offset)
2202 {
2203     char *d = buffer ;
2204     symbol *lbl ;
2205
2206     return;
2207
2208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2209
2210     if (aop->size && offset > ( aop->size - 1)) {
2211         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2212                "pic16_aopPut got offset > aop->size");
2213         exit(0);
2214     }
2215
2216     /* will assign value to value */
2217     /* depending on where it is ofcourse */
2218     switch (aop->type) {
2219     case AOP_DIR:
2220       if (offset) {
2221         sprintf(d,"(%s + %d)",
2222                 aop->aopu.aop_dir,offset);
2223         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2224
2225       } else
2226             sprintf(d,"%s",aop->aopu.aop_dir);
2227         
2228         if (strcmp(d,s)) {
2229           DEBUGpic16_emitcode(";","%d",__LINE__);
2230           if(strcmp(s,"W"))
2231             pic16_emitcode("movf","%s,w",s);
2232           pic16_emitcode("movwf","%s",d);
2233
2234           if(strcmp(s,"W")) {
2235             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2236             if(offset >= aop->size) {
2237               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2238               break;
2239             } else
2240               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2241           }
2242
2243           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2244
2245
2246         }
2247         break;
2248         
2249     case AOP_REG:
2250       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2251         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2252           /*
2253             if (*s == '@'           ||
2254                 strcmp(s,"r0") == 0 ||
2255                 strcmp(s,"r1") == 0 ||
2256                 strcmp(s,"r2") == 0 ||
2257                 strcmp(s,"r3") == 0 ||
2258                 strcmp(s,"r4") == 0 ||
2259                 strcmp(s,"r5") == 0 ||
2260                 strcmp(s,"r6") == 0 || 
2261                 strcmp(s,"r7") == 0 )
2262                 pic16_emitcode("mov","%s,%s  ; %d",
2263                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2264             else
2265           */
2266
2267           if(strcmp(s,"W")==0 )
2268             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2269
2270           pic16_emitcode("movwf","%s",
2271                    aop->aopu.aop_reg[offset]->name);
2272
2273           if(strcmp(s,zero)==0) {
2274             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2275
2276           } else if(strcmp(s,"W")==0) {
2277             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2278             pcop->type = PO_GPR_REGISTER;
2279
2280             PCOR(pcop)->rIdx = -1;
2281             PCOR(pcop)->r = NULL;
2282
2283             DEBUGpic16_emitcode(";","%d",__LINE__);
2284             pcop->name = Safe_strdup(s);
2285             pic16_emitpcode(POC_MOVFW,pcop);
2286             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2287           } else if(strcmp(s,one)==0) {
2288             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2289             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2290           } else {
2291             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2292           }
2293         }
2294         break;
2295         
2296     case AOP_DPTR:
2297     case AOP_DPTR2:
2298     
2299     if (aop->type == AOP_DPTR2)
2300     {
2301         genSetDPTR(1);
2302     }
2303     
2304         if (aop->code) {
2305             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2306                    "pic16_aopPut writting to code space");
2307             exit(0);
2308         }
2309         
2310         while (offset > aop->coff) {
2311             aop->coff++;
2312             pic16_emitcode ("inc","dptr");
2313         }
2314         
2315         while (offset < aop->coff) {
2316             aop->coff-- ;
2317             pic16_emitcode("lcall","__decdptr");
2318         }
2319         
2320         aop->coff = offset;
2321         
2322         /* if not in accumulater */
2323         MOVA(s);        
2324         
2325         pic16_emitcode ("movx","@dptr,a");
2326         
2327     if (aop->type == AOP_DPTR2)
2328     {
2329         genSetDPTR(0);
2330     }
2331         break;
2332         
2333     case AOP_R0:
2334     case AOP_R1:
2335         while (offset > aop->coff) {
2336             aop->coff++;
2337             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2338         }
2339         while (offset < aop->coff) {
2340             aop->coff-- ;
2341             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2342         }
2343         aop->coff = offset;
2344         
2345         if (aop->paged) {
2346             MOVA(s);           
2347             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2348             
2349         } else
2350             if (*s == '@') {
2351                 MOVA(s);
2352                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2353             } else
2354                 if (strcmp(s,"r0") == 0 ||
2355                     strcmp(s,"r1") == 0 ||
2356                     strcmp(s,"r2") == 0 ||
2357                     strcmp(s,"r3") == 0 ||
2358                     strcmp(s,"r4") == 0 ||
2359                     strcmp(s,"r5") == 0 ||
2360                     strcmp(s,"r6") == 0 || 
2361                     strcmp(s,"r7") == 0 ) {
2362                     char buffer[10];
2363                     sprintf(buffer,"a%s",s);
2364                     pic16_emitcode("mov","@%s,%s",
2365                              aop->aopu.aop_ptr->name,buffer);
2366                 } else
2367                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2368         
2369         break;
2370         
2371     case AOP_STK:
2372         if (strcmp(s,"a") == 0)
2373             pic16_emitcode("push","acc");
2374         else
2375             pic16_emitcode("push","%s",s);
2376         
2377         break;
2378         
2379     case AOP_CRY:
2380         /* if bit variable */
2381         if (!aop->aopu.aop_dir) {
2382             pic16_emitcode("clr","a");
2383             pic16_emitcode("rlc","a");
2384         } else {
2385             if (s == zero) 
2386                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2387             else
2388                 if (s == one)
2389                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2390                 else
2391                     if (!strcmp(s,"c"))
2392                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2393                     else {
2394                         lbl = newiTempLabel(NULL);
2395                         
2396                         if (strcmp(s,"a")) {
2397                             MOVA(s);
2398                         }
2399                         pic16_emitcode("clr","c");
2400                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2401                         pic16_emitcode("cpl","c");
2402                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2403                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2404                     }
2405         }
2406         break;
2407         
2408     case AOP_STR:
2409         aop->coff = offset;
2410         if (strcmp(aop->aopu.aop_str[offset],s))
2411             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2412         break;
2413         
2414     case AOP_ACC:
2415         aop->coff = offset;
2416         if (!offset && (strcmp(s,"acc") == 0))
2417             break;
2418         
2419         if (strcmp(aop->aopu.aop_str[offset],s))
2420             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2421         break;
2422
2423     default :
2424         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2425 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2426 //             "pic16_aopPut got unsupported aop->type");
2427 //      exit(0);    
2428     }    
2429
2430 }
2431
2432 /*-----------------------------------------------------------------*/
2433 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2434 /*-----------------------------------------------------------------*/
2435 void pic16_mov2w (asmop *aop, int offset)
2436 {
2437   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2438
2439   if(is_LitAOp(aop))
2440     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2441   else
2442     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2443 }
2444
2445 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2446 {
2447   if(is_LitAOp(src)) {
2448     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2449     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2450   } else {
2451     if(pic16_sameRegsOfs(src, dst, offset))return;
2452     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2453                       pic16_popGet(dst, offset)));
2454   }
2455 }
2456
2457 static void pic16_movLit2f(pCodeOp *pc, int lit)
2458 {
2459   if (0 == (lit & 0x00ff))
2460   {
2461     pic16_emitpcode (POC_CLRF, pc);
2462   } else if (0xff == (lit & 0x00ff))
2463   {
2464     pic16_emitpcode (POC_SETF, pc);
2465   } else {
2466     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2467     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2468   }
2469 }
2470
2471 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2472 {
2473   if(is_LitAOp(src)) {
2474     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2475     pic16_emitpcode(POC_MOVWF, dst);
2476   } else {
2477     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2478   }
2479 }
2480
2481 void pic16_testStackOverflow(void)
2482 {
2483 #define GSTACK_TEST_NAME        "_gstack_test"
2484
2485   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2486   
2487   {
2488     symbol *sym;
2489
2490       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2491       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2492 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2493       checkAddSym(&externs, sym);
2494   }
2495
2496 }
2497
2498 /* push pcop into stack */
2499 void pic16_pushpCodeOp(pCodeOp *pcop)
2500 {
2501 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2502   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2503   if(pic16_options.gstack)
2504     pic16_testStackOverflow();
2505     
2506 }
2507
2508 /* pop pcop from stack */
2509 void pic16_poppCodeOp(pCodeOp *pcop)
2510 {
2511   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2512   if(pic16_options.gstack)
2513     pic16_testStackOverflow();
2514 }
2515
2516
2517 /*-----------------------------------------------------------------*/
2518 /* pushw - pushes wreg to stack                                    */
2519 /*-----------------------------------------------------------------*/
2520 void pushw(void)
2521 {
2522   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2523   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2524   if(pic16_options.gstack)
2525     pic16_testStackOverflow();
2526 }
2527
2528                 
2529 /*-----------------------------------------------------------------*/
2530 /* pushaop - pushes aop to stack                                   */
2531 /*-----------------------------------------------------------------*/
2532 void pushaop(asmop *aop, int offset)
2533 {
2534   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2535
2536   if(_G.resDirect)return;
2537   
2538   if(is_LitAOp(aop)) {
2539     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2540     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2541   } else {
2542     pic16_emitpcode(POC_MOVFF,
2543       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2544   }
2545
2546   if(pic16_options.gstack)
2547     pic16_testStackOverflow();
2548 }
2549
2550 /*-----------------------------------------------------------------*/
2551 /* popaop - pops aop from stack                                    */
2552 /*-----------------------------------------------------------------*/
2553 void popaop(asmop *aop, int offset)
2554 {
2555   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2556   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2557   if(pic16_options.gstack)
2558     pic16_testStackOverflow();
2559 }
2560
2561 void popaopidx(asmop *aop, int offset, int index)
2562 {
2563   int ofs=1;
2564
2565     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2566
2567     if(STACK_MODEL_LARGE)ofs++;
2568
2569     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2570     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2571     if(pic16_options.gstack)
2572       pic16_testStackOverflow();
2573 }
2574
2575 #if !(USE_GENERIC_SIGNED_SHIFT)
2576 /*-----------------------------------------------------------------*/
2577 /* reAdjustPreg - points a register back to where it should        */
2578 /*-----------------------------------------------------------------*/
2579 static void reAdjustPreg (asmop *aop)
2580 {
2581     int size ;
2582
2583     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2584     aop->coff = 0;
2585     if ((size = aop->size) <= 1)
2586         return ;
2587     size-- ;
2588     switch (aop->type) {
2589         case AOP_R0 :
2590         case AOP_R1 :
2591             while (size--)
2592                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2593             break;          
2594         case AOP_DPTR :
2595         case AOP_DPTR2:
2596             if (aop->type == AOP_DPTR2)
2597             {
2598                 genSetDPTR(1);
2599             } 
2600             while (size--)
2601             {
2602                 pic16_emitcode("lcall","__decdptr");
2603             }
2604                 
2605             if (aop->type == AOP_DPTR2)
2606             {
2607                 genSetDPTR(0);
2608             }                
2609             break;  
2610
2611     }   
2612
2613 }
2614 #endif
2615
2616 #if 0
2617 /*-----------------------------------------------------------------*/
2618 /* opIsGptr: returns non-zero if the passed operand is             */   
2619 /* a generic pointer type.                                         */
2620 /*-----------------------------------------------------------------*/ 
2621 static int opIsGptr(operand *op)
2622 {
2623     sym_link *type = operandType(op);
2624     
2625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2626     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2627     {
2628         return 1;
2629     }
2630     return 0;        
2631 }
2632 #endif
2633
2634 /*-----------------------------------------------------------------*/
2635 /* pic16_getDataSize - get the operand data size                         */
2636 /*-----------------------------------------------------------------*/
2637 int pic16_getDataSize(operand *op)
2638 {
2639     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2640
2641
2642     return AOP_SIZE(op);
2643
2644     // tsd- in the pic port, the genptr size is 1, so this code here
2645     // fails. ( in the 8051 port, the size was 4).
2646 #if 0
2647     int size;
2648     size = AOP_SIZE(op);
2649     if (size == GPTRSIZE)
2650     {
2651         sym_link *type = operandType(op);
2652         if (IS_GENPTR(type))
2653         {
2654             /* generic pointer; arithmetic operations
2655              * should ignore the high byte (pointer type).
2656              */
2657             size--;
2658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2659         }
2660     }
2661     return size;
2662 #endif
2663 }
2664
2665 /*-----------------------------------------------------------------*/
2666 /* pic16_outAcc - output Acc                                             */
2667 /*-----------------------------------------------------------------*/
2668 void pic16_outAcc(operand *result)
2669 {
2670   int size,offset;
2671   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2672   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2673
2674
2675   size = pic16_getDataSize(result);
2676   if(size){
2677     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2678     size--;
2679     offset = 1;
2680     /* unsigned or positive */
2681     while(size--)
2682       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2683   }
2684
2685 }
2686
2687 /*-----------------------------------------------------------------*/
2688 /* pic16_outBitC - output a bit C                                  */
2689 /*                 Move to result the value of Carry flag -- VR    */
2690 /*-----------------------------------------------------------------*/
2691 void pic16_outBitC(operand *result)
2692 {
2693   int i;
2694
2695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2696
2697     /* if the result is bit */
2698     if (AOP_TYPE(result) == AOP_CRY) {
2699         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2700         pic16_aopPut(AOP(result),"c",0);
2701     } else {
2702
2703         i = AOP_SIZE(result);
2704         while(i--) {
2705                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2706         }
2707         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2708     }
2709 }
2710
2711 /*-----------------------------------------------------------------*/
2712 /* pic16_outBitOp - output a bit from Op                           */
2713 /*                 Move to result the value of set/clr op -- VR    */
2714 /*-----------------------------------------------------------------*/
2715 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2716 {
2717   int i;
2718
2719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2720
2721     /* if the result is bit */
2722     if (AOP_TYPE(result) == AOP_CRY) {
2723         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2724         pic16_aopPut(AOP(result),"c",0);
2725     } else {
2726
2727         i = AOP_SIZE(result);
2728         while(i--) {
2729                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2730         }
2731         pic16_emitpcode(POC_RRCF, pcop);          
2732         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2733     }
2734 }
2735
2736 /*-----------------------------------------------------------------*/
2737 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2738 /*-----------------------------------------------------------------*/
2739 void pic16_toBoolean(operand *oper)
2740 {
2741     int size = AOP_SIZE(oper) - 1;
2742     int offset = 1;
2743
2744     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2745
2746     if ( AOP_TYPE(oper) != AOP_ACC) {
2747       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2748     }
2749     while (size--) {
2750       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2751     }
2752 }
2753
2754 /*-----------------------------------------------------------------*/
2755 /* genUminusFloat - unary minus for floating points                */
2756 /*-----------------------------------------------------------------*/
2757 static void genUminusFloat(operand *op,operand *result)
2758 {
2759   int size ,offset =0 ;
2760   
2761     FENTRY;
2762     /* for this we just need to flip the 
2763     first it then copy the rest in place */
2764     size = AOP_SIZE(op);
2765     assert( size == AOP_SIZE(result) );
2766
2767     while(size--) {
2768       pic16_mov2f(AOP(result), AOP(op), offset);
2769       offset++;
2770     }
2771     
2772     /* toggle the MSB's highest bit */
2773     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2774 }
2775
2776 /*-----------------------------------------------------------------*/
2777 /* genUminus - unary minus code generation                         */
2778 /*-----------------------------------------------------------------*/
2779 static void genUminus (iCode *ic)
2780 {
2781   int size, i;
2782   sym_link *optype, *rtype;
2783   symbol *label;
2784   int needLabel=0;
2785
2786     FENTRY;     
2787     
2788     /* assign asmops */
2789     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2790     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2791
2792     /* if both in bit space then special case */
2793     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2794       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2795         
2796         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2797         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2798         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2799         goto release; 
2800     } 
2801
2802     optype = operandType(IC_LEFT(ic));
2803     rtype = operandType(IC_RESULT(ic));
2804
2805
2806     /* if float then do float stuff */
2807     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2808       if(IS_FIXED(optype))
2809         debugf("implement fixed16x16 type\n", 0);
2810         
2811         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2812         goto release;
2813     }
2814
2815     /* otherwise subtract from zero by taking the 2's complement */
2816     size = AOP_SIZE(IC_LEFT(ic));
2817     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2818     label = newiTempLabel ( NULL );
2819     
2820     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2821       for (i=size-1; i > 0; i--) {
2822         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2823       } // for
2824       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2825       for (i=1; i < size; i++) {
2826         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2827         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2828       } // for
2829     } else {
2830       for (i=size-1; i >= 0; i--) {
2831         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2832         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2833       } // for
2834       if (size > 1) {
2835         for (i=0; i < size-2; i++) {
2836           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2837           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2838         } // for
2839         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2840       } // if
2841       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2842     }
2843     if (needLabel)
2844       pic16_emitpLabel (label->key);
2845
2846 release:
2847     /* release the aops */
2848     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2849     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2850 }
2851
2852 #if 0
2853 /*-----------------------------------------------------------------*/
2854 /* saveRegisters - will look for a call and save the registers     */
2855 /*-----------------------------------------------------------------*/
2856 static void saveRegisters(iCode *lic) 
2857 {
2858     int i;
2859     iCode *ic;
2860     bitVect *rsave;
2861     sym_link *dtype;
2862
2863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2864     /* look for call */
2865     for (ic = lic ; ic ; ic = ic->next) 
2866         if (ic->op == CALL || ic->op == PCALL)
2867             break;
2868
2869     if (!ic) {
2870         fprintf(stderr,"found parameter push with no function call\n");
2871         return ;
2872     }
2873
2874     /* if the registers have been saved already then
2875     do nothing */
2876     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2877         return ;
2878
2879     /* find the registers in use at this time 
2880     and push them away to safety */
2881     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2882                           ic->rUsed);
2883
2884     ic->regsSaved = 1;
2885     if (options.useXstack) {
2886         if (bitVectBitValue(rsave,R0_IDX))
2887             pic16_emitcode("mov","b,r0");
2888         pic16_emitcode("mov","r0,%s",spname);
2889         for (i = 0 ; i < pic16_nRegs ; i++) {
2890             if (bitVectBitValue(rsave,i)) {
2891                 if (i == R0_IDX)
2892                     pic16_emitcode("mov","a,b");
2893                 else
2894                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2895                 pic16_emitcode("movx","@r0,a");
2896                 pic16_emitcode("inc","r0");
2897             }
2898         }
2899         pic16_emitcode("mov","%s,r0",spname);
2900         if (bitVectBitValue(rsave,R0_IDX))
2901             pic16_emitcode("mov","r0,b");           
2902     }// else
2903     //for (i = 0 ; i < pic16_nRegs ; i++) {
2904     //    if (bitVectBitValue(rsave,i))
2905     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2906     //}
2907
2908     dtype = operandType(IC_LEFT(ic));
2909     if (currFunc && dtype && 
2910         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2911         IFFUNC_ISISR(currFunc->type) &&
2912         !ic->bankSaved) 
2913
2914         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2915
2916 }
2917 /*-----------------------------------------------------------------*/
2918 /* unsaveRegisters - pop the pushed registers                      */
2919 /*-----------------------------------------------------------------*/
2920 static void unsaveRegisters (iCode *ic)
2921 {
2922     int i;
2923     bitVect *rsave;
2924
2925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2926     /* find the registers in use at this time 
2927     and push them away to safety */
2928     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2929                           ic->rUsed);
2930     
2931     if (options.useXstack) {
2932         pic16_emitcode("mov","r0,%s",spname);   
2933         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2934             if (bitVectBitValue(rsave,i)) {
2935                 pic16_emitcode("dec","r0");
2936                 pic16_emitcode("movx","a,@r0");
2937                 if (i == R0_IDX)
2938                     pic16_emitcode("mov","b,a");
2939                 else
2940                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2941             }       
2942
2943         }
2944         pic16_emitcode("mov","%s,r0",spname);
2945         if (bitVectBitValue(rsave,R0_IDX))
2946             pic16_emitcode("mov","r0,b");
2947     } //else
2948     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2949     //    if (bitVectBitValue(rsave,i))
2950     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2951     //}
2952
2953 }  
2954 #endif
2955
2956 #if 0  // patch 14
2957 /*-----------------------------------------------------------------*/
2958 /* pushSide -                                                      */
2959 /*-----------------------------------------------------------------*/
2960 static void pushSide(operand * oper, int size)
2961 {
2962         int offset = 0;
2963     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2964         while (size--) {
2965                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2966                 if (AOP_TYPE(oper) != AOP_REG &&
2967                     AOP_TYPE(oper) != AOP_DIR &&
2968                     strcmp(l,"a") ) {
2969                         pic16_emitcode("mov","a,%s",l);
2970                         pic16_emitcode("push","acc");
2971                 } else
2972                         pic16_emitcode("push","%s",l);
2973         }
2974 }
2975 #endif // patch 14
2976
2977 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2978 {
2979   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2980     pic16_emitpcode(POC_MOVFW, src);
2981     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2982   } else {
2983     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2984         src, pic16_popGet(AOP(op), offset)));
2985   }
2986 }
2987
2988
2989 /*-----------------------------------------------------------------*/
2990 /* assignResultValue - assign results to oper, rescall==1 is       */
2991 /*                     called from genCall() or genPcall()         */
2992 /*-----------------------------------------------------------------*/
2993 static void assignResultValue(operand * oper, int rescall)
2994 {
2995   int size = AOP_SIZE(oper);
2996   int offset=0;
2997   
2998     FENTRY2;
2999 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3000     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3001
3002     if(rescall) {
3003       /* assign result from a call/pcall function() */
3004                 
3005       /* function results are stored in a special order,
3006        * see top of file with Function return policy, or manual */
3007
3008       if(size <= 4) {
3009         /* 8-bits, result in WREG */
3010         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3011                         
3012         if(size>1) {
3013           /* 16-bits, result in PRODL:WREG */
3014           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3015         }
3016                         
3017         if(size>2) {
3018           /* 24-bits, result in PRODH:PRODL:WREG */
3019           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3020         }
3021                         
3022         if(size>3) {
3023           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3024           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3025         }
3026       
3027       } else {
3028         /* >32-bits, result on stack, and FSR0 points to beginning.
3029          * Fix stack when done */
3030         /* FIXME FIXME */
3031 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3032         while (size--) {
3033 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3034 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3035                 
3036           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3037           GpsuedoStkPtr++;
3038         }
3039                         
3040         /* fix stack */
3041         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3042         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3043         if(STACK_MODEL_LARGE) {
3044           emitSKPNC;
3045           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3046         }
3047       }                 
3048     } else {
3049       int areg = 0;             /* matching argument register */
3050       
3051 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3052       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3053
3054
3055       /* its called from genReceive (probably) -- VR */
3056       /* I hope this code will not be called from somewhere else in the future! 
3057        * We manually set the pseudo stack pointer in genReceive. - dw
3058        */
3059       if(!GpsuedoStkPtr && _G.useWreg) {
3060 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3061
3062         /* The last byte in the assignment is in W */
3063         if(areg <= GpsuedoStkPtr) {
3064           size--;
3065           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3066           offset++;
3067 //          debugf("receive from WREG\n", 0);
3068         }
3069         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3070       }
3071 //      GpsuedoStkPtr++;
3072       _G.stack_lat = AOP_SIZE(oper)-1;
3073
3074       while (size) {
3075         size--;
3076         GpsuedoStkPtr++;
3077         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3078 //        debugf("receive from STACK\n", 0);
3079         offset++;
3080       }
3081     }
3082 }
3083
3084
3085 /*-----------------------------------------------------------------*/
3086 /* genIpush - generate code for pushing this gets a little complex */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpush (iCode *ic)
3089 {
3090 //  int size, offset=0;
3091
3092   FENTRY;
3093   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3094
3095   if(ic->parmPush) {
3096     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3097
3098     /* send to stack as normal */
3099     addSet(&_G.sendSet,ic);
3100 //    addSetHead(&_G.sendSet,ic);
3101     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3102   }
3103
3104         
3105 #if 0
3106     int size, offset = 0 ;
3107     char *l;
3108
3109
3110     /* if this is not a parm push : ie. it is spill push 
3111     and spill push is always done on the local stack */
3112     if (!ic->parmPush) {
3113
3114         /* and the item is spilt then do nothing */
3115         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3116             return ;
3117
3118         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3119         size = AOP_SIZE(IC_LEFT(ic));
3120         /* push it on the stack */
3121         while(size--) {
3122             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3123             if (*l == '#') {
3124                 MOVA(l);
3125                 l = "acc";
3126             }
3127             pic16_emitcode("push","%s",l);
3128         }
3129         return ;        
3130     }
3131
3132     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3133 #endif
3134 }
3135
3136 /*-----------------------------------------------------------------*/
3137 /* genIpop - recover the registers: can happen only for spilling   */
3138 /*-----------------------------------------------------------------*/
3139 static void genIpop (iCode *ic)
3140 {
3141   FENTRY;
3142   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3143 #if 0
3144     int size,offset ;
3145
3146
3147     /* if the temp was not pushed then */
3148     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3149         return ;
3150
3151     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3152     size = AOP_SIZE(IC_LEFT(ic));
3153     offset = (size-1);
3154     while (size--) 
3155         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3156                                    FALSE,TRUE));
3157
3158     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3159 #endif
3160 }
3161
3162 #if 0
3163 /*-----------------------------------------------------------------*/
3164 /* unsaverbank - restores the resgister bank from stack            */
3165 /*-----------------------------------------------------------------*/
3166 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3167 {
3168   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3169 #if 0
3170     int i;
3171     asmop *aop ;
3172     regs *r = NULL;
3173
3174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3175     if (popPsw) {
3176         if (options.useXstack) {
3177             aop = newAsmop(0);
3178             r = getFreePtr(ic,&aop,FALSE);
3179             
3180             
3181             pic16_emitcode("mov","%s,_spx",r->name);
3182             pic16_emitcode("movx","a,@%s",r->name);
3183             pic16_emitcode("mov","psw,a");
3184             pic16_emitcode("dec","%s",r->name);
3185             
3186         }else
3187             pic16_emitcode ("pop","psw");
3188     }
3189
3190     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3191         if (options.useXstack) {       
3192             pic16_emitcode("movx","a,@%s",r->name);
3193             //pic16_emitcode("mov","(%s+%d),a",
3194             //       regspic16[i].base,8*bank+regspic16[i].offset);
3195             pic16_emitcode("dec","%s",r->name);
3196
3197         } else 
3198           pic16_emitcode("pop",""); //"(%s+%d)",
3199         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3200     }
3201
3202     if (options.useXstack) {
3203
3204         pic16_emitcode("mov","_spx,%s",r->name);
3205         pic16_freeAsmop(NULL,aop,ic,TRUE);
3206
3207     }
3208 #endif 
3209 }
3210
3211 /*-----------------------------------------------------------------*/
3212 /* saverbank - saves an entire register bank on the stack          */
3213 /*-----------------------------------------------------------------*/
3214 static void saverbank (int bank, iCode *ic, bool pushPsw)
3215 {
3216   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3217 #if 0
3218     int i;
3219     asmop *aop ;
3220     regs *r = NULL;
3221
3222     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3223     if (options.useXstack) {
3224
3225         aop = newAsmop(0);
3226         r = getFreePtr(ic,&aop,FALSE);  
3227         pic16_emitcode("mov","%s,_spx",r->name);
3228
3229     }
3230
3231     for (i = 0 ; i < pic16_nRegs ;i++) {
3232         if (options.useXstack) {
3233             pic16_emitcode("inc","%s",r->name);
3234             //pic16_emitcode("mov","a,(%s+%d)",
3235             //         regspic16[i].base,8*bank+regspic16[i].offset);
3236             pic16_emitcode("movx","@%s,a",r->name);           
3237         } else 
3238           pic16_emitcode("push","");// "(%s+%d)",
3239                      //regspic16[i].base,8*bank+regspic16[i].offset);
3240     }
3241     
3242     if (pushPsw) {
3243         if (options.useXstack) {
3244             pic16_emitcode("mov","a,psw");
3245             pic16_emitcode("movx","@%s,a",r->name);     
3246             pic16_emitcode("inc","%s",r->name);
3247             pic16_emitcode("mov","_spx,%s",r->name);       
3248             pic16_freeAsmop (NULL,aop,ic,TRUE);
3249             
3250         } else
3251             pic16_emitcode("push","psw");
3252         
3253         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3254     }
3255     ic->bankSaved = 1;
3256 #endif
3257 }
3258 #endif  /* 0 */
3259
3260
3261 static int wparamCmp(void *p1, void *p2)
3262 {
3263   return (!strcmp((char *)p1, (char *)p2));
3264 }
3265
3266 int inWparamList(char *s)
3267 {
3268   return isinSetWith(wparamList, s, wparamCmp);
3269
3270
3271
3272 /*-----------------------------------------------------------------*/
3273 /* genCall - generates a call statement                            */
3274 /*-----------------------------------------------------------------*/
3275 static void genCall (iCode *ic)
3276 {
3277   sym_link *ftype;   
3278   int stackParms=0;
3279   int use_wreg=0;
3280   int inwparam=0;
3281   char *fname;
3282   
3283     FENTRY;
3284
3285     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3286     /* if caller saves & we have not saved then */
3287 //    if (!ic->regsSaved)
3288 //      saveRegisters(ic);
3289
3290         /* initialise stackParms for IPUSH pushes */
3291 //      stackParms = psuedoStkPtr;
3292 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3293     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3294     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3295
3296 #if 0
3297     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3298 #endif
3299
3300     /* if send set is not empty the assign */
3301     if (_G.sendSet) {
3302       iCode *sic;
3303       int psuedoStkPtr=-1; 
3304       int firstTimeThruLoop = 1;
3305
3306
3307         /* reverse sendSet if function is not reentrant */
3308         if(!IFFUNC_ISREENT(ftype))
3309           _G.sendSet = reverseSet(_G.sendSet);
3310
3311         /* First figure how many parameters are getting passed */
3312         stackParms = 0;
3313         use_wreg = 0;
3314         
3315         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3316           int size;
3317 //          int offset = 0;
3318
3319             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3320             size = AOP_SIZE(IC_LEFT(sic));
3321
3322             stackParms += size;
3323
3324             /* pass the last byte through WREG */
3325             if(inwparam) {
3326
3327               while (size--) {
3328                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3329                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3330                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3331
3332                 if(!firstTimeThruLoop) {
3333                   /* If this is not the first time we've been through the loop
3334                    * then we need to save the parameter in a temporary
3335                    * register. The last byte of the last parameter is
3336                    * passed in W. */
3337
3338                   pushw();
3339 //                  --psuedoStkPtr;             // sanity check
3340                   use_wreg = 1;
3341                 }
3342                 
3343                 firstTimeThruLoop=0;
3344
3345                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3346
3347 //                offset++;
3348               }
3349             } else {
3350               /* all arguments are passed via stack */
3351               use_wreg = 0;
3352
3353               while (size--) {
3354                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3355                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3356                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3357
3358 //                pushaop(AOP(IC_LEFT(sic)), size);
3359                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3360                                 
3361                 if(!_G.resDirect)
3362                   pushw();
3363               }
3364             }
3365
3366             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3367           }
3368
3369           if(inwparam) {
3370             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3371               pushw();  /* save last parameter to stack if functions has varargs */
3372               use_wreg = 0;
3373             } else
3374               use_wreg = 1;
3375           } else use_wreg = 0;
3376
3377           _G.stackRegSet = _G.sendSet;
3378           _G.sendSet = NULL;
3379     }
3380
3381     /* make the call */
3382     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3383
3384     GpsuedoStkPtr=0;
3385     
3386     /* if we need to assign a result value */
3387     if ((IS_ITEMP(IC_RESULT(ic))
3388           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3389               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3390         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3391
3392       _G.accInUse++;
3393       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3394       _G.accInUse--;
3395
3396       assignResultValue(IC_RESULT(ic), 1);
3397
3398       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3399                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3400                 
3401       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3402     }
3403
3404     if(!stackParms && ic->parmBytes) {
3405       stackParms = ic->parmBytes;
3406     }
3407       
3408     stackParms -= use_wreg;
3409     
3410     if(stackParms>0) {
3411       if(stackParms == 1) {
3412         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3413       } else {
3414         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3415         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3416       }
3417       if(STACK_MODEL_LARGE) {
3418         emitSKPNC;
3419         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3420       }
3421     }
3422
3423 #if 0
3424     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3425 #endif
3426
3427     /* adjust the stack for parameters if required */
3428 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3429
3430 #if 0
3431       /* if register bank was saved then pop them */
3432       if (ic->bankSaved)
3433         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3434
3435       /* if we hade saved some registers then unsave them */
3436       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3437         unsaveRegisters (ic);
3438 #endif
3439 }
3440
3441
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genPcall - generates a call by pointer statement                */
3445 /*            new version, created from genCall - HJD              */
3446 /*-----------------------------------------------------------------*/
3447 static void genPcall (iCode *ic)
3448 {
3449   sym_link *fntype;
3450   int stackParms=0;
3451   symbol *retlbl = newiTempLabel(NULL);
3452   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3453   
3454     FENTRY;
3455
3456     fntype = operandType( IC_LEFT(ic) )->next;
3457
3458     /* if send set is not empty the assign */
3459     if (_G.sendSet) {
3460       iCode *sic;
3461       int psuedoStkPtr=-1; 
3462
3463       /* reverse sendSet if function is not reentrant */
3464       if(!IFFUNC_ISREENT(fntype))
3465         _G.sendSet = reverseSet(_G.sendSet);
3466
3467       stackParms = 0;
3468       
3469       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3470         int size;
3471
3472           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3473           size = AOP_SIZE(IC_LEFT(sic));
3474           stackParms += size;
3475
3476           /* all parameters are passed via stack, since WREG is clobbered
3477            * by the calling sequence */
3478           while (size--) {
3479             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3480             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3481             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3482
3483             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3484             pushw();
3485           }
3486
3487           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3488       }
3489
3490       _G.stackRegSet = _G.sendSet;
3491       _G.sendSet = NULL;
3492     }
3493
3494     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3495
3496     // push return address
3497     // push $ on return stack, then replace with retlbl
3498
3499     /* Thanks to Thorsten Klose for pointing out that the following
3500      * snippet should be interrupt safe */
3501     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3502     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3503
3504     pic16_emitpcodeNULLop(POC_PUSH);
3505
3506     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3507     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3508     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3509     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3510     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3511     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3512
3513
3514     /* restore interrupt control register */
3515     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3516     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3517
3518     /* make the call by writing the pointer into pc */
3519     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3520     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3521
3522     // note: MOVFF to PCL not allowed
3523     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3524     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3525
3526
3527     /* return address is here: (X) */
3528     pic16_emitpLabelFORCE(retlbl->key);
3529
3530     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3531
3532     GpsuedoStkPtr=0;
3533     /* if we need assign a result value */
3534     if ((IS_ITEMP(IC_RESULT(ic))
3535           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3536               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3537         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3538
3539       _G.accInUse++;
3540       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3541       _G.accInUse--;
3542
3543       assignResultValue(IC_RESULT(ic), 1);
3544
3545       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3546               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3547                 
3548       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3549     }
3550
3551 //    stackParms -= use_wreg;
3552     
3553     if(stackParms>0) {
3554       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3555       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3556       if(STACK_MODEL_LARGE) {
3557         emitSKPNC;
3558         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3559       }
3560     }
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* resultRemat - result  is rematerializable                       */
3565 /*-----------------------------------------------------------------*/
3566 static int resultRemat (iCode *ic)
3567 {
3568   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3569   if (SKIP_IC(ic) || ic->op == IFX)
3570     return 0;
3571
3572   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3573     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3574     if (sym->remat && !POINTER_SET(ic)) 
3575       return 1;
3576   }
3577
3578   return 0;
3579 }
3580
3581 #if defined(__BORLANDC__) || defined(_MSC_VER)
3582 #define STRCASECMP stricmp
3583 #else
3584 #define STRCASECMP strcasecmp
3585 #endif
3586
3587 #if 0
3588 /*-----------------------------------------------------------------*/
3589 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3590 /*-----------------------------------------------------------------*/
3591 static bool inExcludeList(char *s)
3592 {
3593   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3594     int i =0;
3595     
3596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3597     if (options.excludeRegs[i] &&
3598     STRCASECMP(options.excludeRegs[i],"none") == 0)
3599         return FALSE ;
3600
3601     for ( i = 0 ; options.excludeRegs[i]; i++) {
3602         if (options.excludeRegs[i] &&
3603         STRCASECMP(s,options.excludeRegs[i]) == 0)
3604             return TRUE;
3605     }
3606     return FALSE ;
3607 }
3608 #endif
3609
3610 /*-----------------------------------------------------------------*/
3611 /* genFunction - generated code for function entry                 */
3612 /*-----------------------------------------------------------------*/
3613 static void genFunction (iCode *ic)
3614 {
3615   symbol *sym;
3616   sym_link *ftype;
3617   
3618     FENTRY;
3619     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3620
3621     pic16_labelOffset += (max_key+4);
3622     max_key=0;
3623     GpsuedoStkPtr=0;
3624     _G.nRegsSaved = 0;
3625         
3626     ftype = operandType(IC_LEFT(ic));
3627     sym = OP_SYMBOL(IC_LEFT(ic));
3628
3629     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3630       /* create an absolute section at the interrupt vector:
3631        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3632       symbol *asym;
3633       char asymname[128];
3634       pBlock *apb;
3635
3636 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3637
3638         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3639           sprintf(asymname, "ivec_%s", sym->name);
3640         else
3641           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3642   
3643         /* when an interrupt is declared as naked, do not emit the special
3644          * wrapper segment at vector address. The user should take care for
3645          * this instead. -- VR */
3646
3647         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3648           asym = newSymbol(asymname, 0);
3649           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3650           pic16_addpBlock( apb );
3651
3652           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3653           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3654           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3655           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3656           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3657                 
3658           /* mark the end of this tiny function */
3659           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3660         } else {
3661           sprintf(asymname, "%s", sym->rname);
3662         }
3663
3664         {
3665           absSym *abSym;
3666
3667             abSym = Safe_calloc(1, sizeof(absSym));
3668             strcpy(abSym->name, asymname);
3669
3670             switch( FUNC_INTNO(sym->type) ) {
3671               case 0: abSym->address = 0x000000; break;
3672               case 1: abSym->address = 0x000008; break;
3673               case 2: abSym->address = 0x000018; break;
3674               
3675               default:
3676 //                fprintf(stderr, "no interrupt number is given\n");
3677                 abSym->address = -1; break;
3678             }
3679
3680             /* relocate interrupt vectors if needed */
3681             if(abSym->address != -1)
3682               abSym->address += pic16_options.ivt_loc;
3683
3684             addSet(&absSymSet, abSym);
3685         }
3686     }
3687
3688     /* create the function header */
3689     pic16_emitcode(";","-----------------------------------------");
3690     pic16_emitcode(";"," function %s",sym->name);
3691     pic16_emitcode(";","-----------------------------------------");
3692
3693     pic16_emitcode("","%s:",sym->rname);
3694     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3695
3696     {
3697       absSym *ab;
3698
3699         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3700           if(!strcmp(ab->name, sym->rname)) {
3701             pic16_pBlockConvert2Absolute(pb);
3702             break;
3703           }
3704         }
3705     }
3706
3707     if(IFFUNC_ISNAKED(ftype)) {
3708       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3709       return;
3710     }
3711         
3712     /* if critical function then turn interrupts off */
3713     if (IFFUNC_ISCRITICAL(ftype)) {
3714       //pic16_emitcode("clr","ea");
3715     }
3716
3717     currFunc = sym;             /* update the currFunc symbol */
3718     _G.fregsUsed = sym->regsUsed;
3719     _G.sregsAlloc = newBitVect(128);
3720     
3721
3722     /* if this is an interrupt service routine then
3723      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3724     if (IFFUNC_ISISR(sym->type)) {
3725         _G.usefastretfie = 1;   /* use shadow registers by default */
3726         
3727         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3728         if(!FUNC_ISSHADOWREGS(sym->type)) {
3729           /* do not save WREG,STATUS,BSR for high priority interrupts
3730            * because they are stored in the hardware shadow registers already */
3731           _G.usefastretfie = 0;
3732           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3733           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3734           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3735         }
3736
3737         /* these should really be optimized somehow, because not all
3738          * interrupt handlers modify them */
3739         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3740         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3741         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3742         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3743         
3744 //        pic16_pBlockConvert2ISR(pb);
3745     }
3746
3747     /* emit code to setup stack frame if user enabled,
3748      * and function is not main() */
3749     
3750 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3751     if(strcmp(sym->name, "main")) {
3752       if(0 
3753         || !options.ommitFramePtr 
3754 //        || sym->regsUsed
3755         || IFFUNC_ARGS(sym->type)
3756         || FUNC_HASSTACKPARM(sym->etype)
3757         ) {
3758         /* setup the stack frame */
3759         if(STACK_MODEL_LARGE)
3760           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3761         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3762
3763         if(STACK_MODEL_LARGE)
3764           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3765         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3766       }
3767     }
3768
3769     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3770           && sym->stack) {
3771
3772       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3773
3774       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3775       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3776       emitSKPC;
3777       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3778     }
3779           
3780     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3781       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3782         _G.useWreg = 0;
3783       else
3784         _G.useWreg = 1;
3785     } else
3786       _G.useWreg = 0;
3787
3788     /* if callee-save to be used for this function
3789      * then save the registers being used in this function */
3790 //    if (IFFUNC_CALLEESAVES(sym->type))
3791     if(strcmp(sym->name, "main")) {
3792       int i;
3793
3794         /* if any registers used */
3795         if (sym->regsUsed) {
3796                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3797
3798           if(!xinst) {
3799             /* save the registers used */
3800             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3801             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3802               if (bitVectBitValue(sym->regsUsed,i)) {
3803 #if 0
3804                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3805 #endif
3806                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3807                 _G.nRegsSaved++;
3808
3809                 if(!pic16_regWithIdx(i)->wasUsed) {
3810                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3811                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3812                   pic16_regWithIdx(i)->wasUsed = 1;
3813                 }
3814               }
3815             }
3816           } else {
3817             
3818             /* xinst */
3819             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3820             for(i=0;i<sym->regsUsed->size;i++) {
3821               if(bitVectBitValue(sym->regsUsed, i)) {
3822                 _G.nRegsSaved++;
3823               }
3824             }
3825                         
3826 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3827           }
3828
3829           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3830
3831         }
3832     }
3833         
3834     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3835 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3836 }
3837
3838 /*-----------------------------------------------------------------*/
3839 /* genEndFunction - generates epilogue for functions               */
3840 /*-----------------------------------------------------------------*/
3841 static void genEndFunction (iCode *ic)
3842 {
3843   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3844
3845     FENTRY;
3846
3847     if(IFFUNC_ISNAKED(sym->type)) {
3848       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3849       return;
3850     }
3851
3852     _G.stack_lat = 0;
3853
3854     /* add code for ISCRITICAL */
3855     if(IFFUNC_ISCRITICAL(sym->type)) {
3856       /* if critical function, turn on interrupts */
3857       
3858       /* TODO: add code here -- VR */
3859     }
3860     
3861 //    sym->regsUsed = _G.fregsUsed;
3862     
3863     /* now we need to restore the registers */
3864     /* if any registers used */
3865
3866     /* first restore registers that might be used for stack access */
3867     if(_G.sregsAllocSet) {
3868     regs *sr;
3869     
3870       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3871       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3872         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3873       }
3874     }
3875
3876     if (strcmp(sym->name, "main") && sym->regsUsed) {
3877       int i;
3878
3879         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3880         /* restore registers used */
3881         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3882         for ( i = sym->regsUsed->size; i >= 0; i--) {
3883           if (bitVectBitValue(sym->regsUsed,i)) {
3884             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3885             _G.nRegsSaved--;
3886           }
3887         }
3888         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3889     }
3890
3891       
3892
3893     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3894           && sym->stack) {
3895       if (sym->stack == 1) {
3896         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3897         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3898       } else {
3899         // we have to add more than one...
3900         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3901         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3902         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3903         emitSKPNC;
3904         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3905         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3906         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3907       }
3908     }
3909
3910     if(strcmp(sym->name, "main")) {
3911       if(0
3912         || !options.ommitFramePtr
3913 //        || sym->regsUsed
3914         || IFFUNC_ARGS(sym->type)
3915         || FUNC_HASSTACKPARM(sym->etype)
3916         ) {
3917         /* restore stack frame */
3918         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3919         if(STACK_MODEL_LARGE)
3920           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3921       }
3922     }
3923
3924     _G.useWreg = 0;
3925
3926     if (IFFUNC_ISISR(sym->type)) {
3927       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3928       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3929       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3930       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3931
3932       if(!FUNC_ISSHADOWREGS(sym->type)) {
3933         /* do not restore interrupt vector for WREG,STATUS,BSR
3934          * for high priority interrupt, see genFunction */
3935         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3936         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3937         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3938       }
3939 //      _G.interruptvector = 0;         /* sanity check */
3940
3941
3942       /* if debug then send end of function */
3943 /*      if (options.debug && currFunc)  */
3944       if (currFunc) {
3945         debugFile->writeEndFunction (currFunc, ic, 1);
3946       }
3947         
3948       if(_G.usefastretfie)
3949         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3950       else
3951         pic16_emitpcodeNULLop(POC_RETFIE);
3952
3953       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3954       
3955       _G.usefastretfie = 0;
3956       return;
3957     }
3958
3959     if (IFFUNC_ISCRITICAL(sym->type)) {
3960       pic16_emitcode("setb","ea");
3961     }
3962
3963     /* if debug then send end of function */
3964     if (currFunc) {
3965       debugFile->writeEndFunction (currFunc, ic, 1);
3966     }
3967
3968     /* insert code to restore stack frame, if user enabled it
3969      * and function is not main() */
3970          
3971
3972     pic16_emitpcodeNULLop(POC_RETURN);
3973
3974     /* Mark the end of a function */
3975     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3976 }
3977
3978
3979 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3980 {
3981   unsigned long lit=1;
3982   operand *op;
3983   
3984     op = IC_LEFT(ic);
3985   
3986     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3987     if(AOP_TYPE(op) == AOP_LIT) {
3988       if(!IS_FLOAT(operandType( op ))) {
3989         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3990       } else {
3991         union {
3992           unsigned long lit_int;
3993           float lit_float;
3994         } info;
3995         
3996         /* take care if literal is a float */
3997         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3998         lit = info.lit_int;
3999       }
4000     }
4001
4002     if (AOP_TYPE(op) == AOP_LIT) {
4003       /* FIXME: broken for
4004        *   char __at(0x456) foo;
4005        *   return &foo;
4006        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4007       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4008     } else if (AOP_TYPE(op) == AOP_PCODE
4009                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4010       /* char *s= "aaa"; return s; */
4011       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4012        *      that the generic pointer is interpreted correctly
4013        *      as referring to __code space, but this is fragile! */
4014       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4015       /* XXX: should check that dest != WREG */
4016       pic16_emitpcode(POC_MOVWF, dest);
4017     } else {
4018       if(dest->type == PO_WREG && (offset == 0)) {
4019         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4020         return;
4021       }
4022       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4023     }
4024 }
4025
4026 /*-----------------------------------------------------------------*/
4027 /* genRet - generate code for return statement                     */
4028 /*-----------------------------------------------------------------*/
4029 static void genRet (iCode *ic)
4030 {
4031   int size;
4032   operand *left;
4033
4034     FENTRY;
4035         /* if we have no return value then
4036          * just generate the "ret" */
4037         
4038         if (!IC_LEFT(ic)) 
4039                 goto jumpret;       
4040     
4041         /* we have something to return then
4042          * move the return value into place */
4043         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4044         size = AOP_SIZE(IC_LEFT(ic));
4045
4046         if(size <= 4) {
4047           if(size>3)
4048             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4049           
4050           if(size>2)
4051             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4052
4053           if(size>1)
4054             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4055           
4056           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4057
4058         } else {
4059                 /* >32-bits, setup stack and FSR0 */
4060                 while (size--) {
4061 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4062 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4063
4064                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4065
4066 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4067                         GpsuedoStkPtr++;
4068                 }
4069                         
4070                 /* setup FSR0 */
4071                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4073
4074                 if(STACK_MODEL_LARGE) {
4075                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4076                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4077                 } else {
4078                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4079                 }
4080         }
4081                                 
4082 #if 0
4083         /* old code, left here for reference -- VR */    
4084         while (size--) {
4085           char *l ;
4086
4087                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4088                         /* #NOCHANGE */
4089                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4090                         pic16_emitpcomment("push %s",l);
4091                         pushed++;
4092                 } else {
4093                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4094                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4095                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4096                         
4097                         if (strcmp(fReturn[offset],l)) {
4098                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4099                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4100                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4101                                 } else {
4102                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4103                                 }
4104                                 
4105                                 if(size) {
4106                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4107                                 }
4108                                 offset++;
4109                         }
4110                 }
4111         }    
4112
4113         if (pushed) {
4114                 while(pushed) {
4115                         pushed--;
4116                         if (strcmp(fReturn[pushed],"a"))
4117                                 pic16_emitcode("pop",fReturn[pushed]);
4118                         else
4119                                 pic16_emitcode("pop","acc");
4120                 }
4121         }
4122 #endif
4123
4124
4125         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4126     
4127 jumpret:
4128         /* generate a jump to the return label
4129          * if the next is not the return statement */
4130         if (!(ic->next && ic->next->op == LABEL
4131                 && IC_LABEL(ic->next) == returnLabel)) {
4132         
4133                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4134                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4135         }
4136 }
4137
4138 /*-----------------------------------------------------------------*/
4139 /* genLabel - generates a label                                    */
4140 /*-----------------------------------------------------------------*/
4141 static void genLabel (iCode *ic)
4142 {
4143   FENTRY;
4144
4145   /* special case never generate */
4146   if (IC_LABEL(ic) == entryLabel)
4147     return ;
4148
4149   pic16_emitpLabel(IC_LABEL(ic)->key);
4150 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a goto                                      */
4155 /*-----------------------------------------------------------------*/
4156 //tsd
4157 static void genGoto (iCode *ic)
4158 {
4159   FENTRY;
4160   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4161 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4162 }
4163
4164
4165 /*-----------------------------------------------------------------*/
4166 /* genMultbits :- multiplication of bits                           */
4167 /*-----------------------------------------------------------------*/
4168 static void genMultbits (operand *left, 
4169                          operand *right, 
4170                          operand *result)
4171 {
4172   FENTRY;
4173
4174   if(!pic16_sameRegs(AOP(result),AOP(right)))
4175     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4176
4177   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4178   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4179   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4180
4181 }
4182
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneByte : 8 bit multiplication & division                */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneByte (operand *left,
4188                             operand *right,
4189                             operand *result)
4190 {
4191
4192   FENTRY;
4193   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4194   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4195
4196   /* (if two literals, the value is computed before) */
4197   /* if one literal, literal on the right */
4198   if (AOP_TYPE(left) == AOP_LIT){
4199     operand *t = right;
4200     right = left;
4201     left = t;
4202   }
4203
4204         /* size is already checked in genMult == 1 */
4205 //      size = AOP_SIZE(result);
4206
4207         if (AOP_TYPE(right) == AOP_LIT){
4208                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4209                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4210                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4211                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212         } else {
4213                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4214                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4215                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4216                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4217         }
4218         
4219         pic16_genMult8X8_8 (left, right,result);
4220 }
4221
4222 /*-----------------------------------------------------------------*/
4223 /* genMultOneWord : 16 bit multiplication                          */
4224 /*-----------------------------------------------------------------*/
4225 static void genMultOneWord (operand *left,
4226                             operand *right,
4227                             operand *result)
4228 {
4229   FENTRY;
4230   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4231   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4232
4233   /* (if two literals, the value is computed before)
4234    * if one literal, literal on the right */
4235   if (AOP_TYPE(left) == AOP_LIT){
4236     operand *t = right;
4237     right = left;
4238     left = t;
4239   }
4240
4241   /* size is checked already == 2 */
4242 //  size = AOP_SIZE(result);
4243
4244   if (AOP_TYPE(right) == AOP_LIT) {
4245     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4246       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4247       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4248       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4249   } else {
4250     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4251       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4252       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4253       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4254   }
4255         
4256   pic16_genMult16X16_16(left, right,result);
4257 }
4258
4259 /*-----------------------------------------------------------------*/
4260 /* genMultOneLong : 32 bit multiplication                          */
4261 /*-----------------------------------------------------------------*/
4262 static void genMultOneLong (operand *left,
4263                             operand *right,
4264                             operand *result)
4265 {
4266   FENTRY;
4267   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4268   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4269
4270   /* (if two literals, the value is computed before)
4271    * if one literal, literal on the right */
4272   if (AOP_TYPE(left) == AOP_LIT){
4273     operand *t = right;
4274     right = left;
4275     left = t;
4276   }
4277
4278   /* size is checked already == 4 */
4279 //  size = AOP_SIZE(result);
4280
4281   if (AOP_TYPE(right) == AOP_LIT) {
4282     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4283         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4284         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4285         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4286   } else {
4287     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4288         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4289         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4290         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4291   }
4292         
4293   pic16_genMult32X32_32(left, right,result);
4294 }
4295
4296
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genMult - generates code for multiplication                     */
4300 /*-----------------------------------------------------------------*/
4301 static void genMult (iCode *ic)
4302 {
4303   operand *left = IC_LEFT(ic);
4304   operand *right = IC_RIGHT(ic);
4305   operand *result= IC_RESULT(ic);   
4306
4307     FENTRY;
4308         /* assign the amsops */
4309         pic16_aopOp (left,ic,FALSE);
4310         pic16_aopOp (right,ic,FALSE);
4311         pic16_aopOp (result,ic,TRUE);
4312
4313         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4314
4315         /* special cases first *
4316         * both are bits */
4317         if (AOP_TYPE(left) == AOP_CRY
4318                 && AOP_TYPE(right)== AOP_CRY) {
4319                 genMultbits(left,right,result);
4320           goto release ;
4321         }
4322
4323         /* if both are of size == 1 */
4324         if(AOP_SIZE(left) == 1
4325                 && AOP_SIZE(right) == 1) {
4326                 genMultOneByte(left,right,result);
4327           goto release ;
4328         }
4329
4330         /* if both are of size == 2 */
4331         if(AOP_SIZE(left) == 2
4332                 && AOP_SIZE(right) == 2) {
4333                 genMultOneWord(left, right, result);
4334           goto release;
4335         }
4336         
4337         /* if both are of size == 4 */
4338         if(AOP_SIZE(left) == 4
4339                 && AOP_SIZE(right) == 4) {
4340                 genMultOneLong(left, right, result);
4341           goto release;
4342         }
4343         
4344         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4345
4346
4347         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4348         /* should have been converted to function call */
4349         assert(0) ;
4350
4351 release :
4352         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354         pic16_freeAsmop(result,NULL,ic,TRUE); 
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genDivbits :- division of bits                                  */
4359 /*-----------------------------------------------------------------*/
4360 static void genDivbits (operand *left, 
4361                         operand *right, 
4362                         operand *result)
4363 {
4364   char *l;
4365
4366     FENTRY;
4367     /* the result must be bit */    
4368     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4369     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4370
4371     MOVA(l);    
4372
4373     pic16_emitcode("div","ab");
4374     pic16_emitcode("rrc","a");
4375     pic16_aopPut(AOP(result),"c",0);
4376 }
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genDivOneByte : 8 bit division                                  */
4380 /*-----------------------------------------------------------------*/
4381 static void genDivOneByte (operand *left,
4382                            operand *right,
4383                            operand *result)
4384 {
4385   sym_link *opetype = operandType(result);
4386   char *l ;
4387   symbol *lbl ;
4388   int size,offset;
4389
4390         /* result = divident / divisor
4391          * - divident may be a register or a literal,
4392          * - divisor may be a register or a literal,
4393          * so there are 3 cases (literal / literal is optimized
4394          * by the front-end) to handle.
4395          * In addition we must handle signed and unsigned, which
4396          * result in 6 final different cases -- VR */
4397
4398     FENTRY;
4399     
4400     size = AOP_SIZE(result) - 1;
4401     offset = 1;
4402     /* signed or unsigned */
4403     if (SPEC_USIGN(opetype)) {
4404       pCodeOp *pct1,    /* count */
4405                 *pct2,  /* reste */
4406                 *pct3;  /* temp */
4407       symbol *label1, *label2, *label3;;
4408
4409
4410         /* unsigned is easy */
4411
4412         pct1 = pic16_popGetTempReg(1);
4413         pct2 = pic16_popGetTempReg(1);
4414         pct3 = pic16_popGetTempReg(1);
4415         
4416         label1 = newiTempLabel(NULL);
4417         label2 = newiTempLabel(NULL);
4418         label3 = newiTempLabel(NULL);
4419
4420         /* the following algorithm is extracted from divuint.c */
4421
4422         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4423         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4424         
4425         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4426
4427         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4428         
4429         pic16_emitpLabel(label1->key);
4430         
4431         emitCLRC;
4432         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4433
4434
4435         emitCLRC;
4436         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4437         
4438
4439         emitSKPNC;
4440         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4441         
4442         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4443         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4444         
4445         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4446         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4447         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4448         
4449         pic16_emitpLabel( label3->key );
4450         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4451         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4452         
4453         
4454
4455         pic16_emitpLabel(label2->key);
4456         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4457         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4458         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4459         
4460         /* result is in wreg */
4461         if(AOP_TYPE(result) != AOP_ACC)
4462                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4463
4464         pic16_popReleaseTempReg( pct3, 1);
4465         pic16_popReleaseTempReg( pct2, 1);
4466         pic16_popReleaseTempReg( pct1, 1);
4467
4468         return ;
4469     }
4470
4471     /* signed is a little bit more difficult */
4472
4473     /* save the signs of the operands */
4474     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4475     MOVA(l);    
4476     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4477     pic16_emitcode("push","acc"); /* save it on the stack */
4478
4479     /* now sign adjust for both left & right */
4480     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4481     MOVA(l);       
4482     lbl = newiTempLabel(NULL);
4483     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4484     pic16_emitcode("cpl","a");   
4485     pic16_emitcode("inc","a");
4486     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4487     pic16_emitcode("mov","b,a");
4488
4489     /* sign adjust left side */
4490     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4491     MOVA(l);
4492
4493     lbl = newiTempLabel(NULL);
4494     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4495     pic16_emitcode("cpl","a");
4496     pic16_emitcode("inc","a");
4497     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4498
4499     /* now the division */
4500     pic16_emitcode("div","ab");
4501     /* we are interested in the lower order
4502     only */
4503     pic16_emitcode("mov","b,a");
4504     lbl = newiTempLabel(NULL);
4505     pic16_emitcode("pop","acc");   
4506     /* if there was an over flow we don't 
4507     adjust the sign of the result */
4508     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4509     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4510     CLRC;
4511     pic16_emitcode("clr","a");
4512     pic16_emitcode("subb","a,b");
4513     pic16_emitcode("mov","b,a");
4514     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4515
4516     /* now we are done */
4517     pic16_aopPut(AOP(result),"b",0);
4518     if(size > 0){
4519         pic16_emitcode("mov","c,b.7");
4520         pic16_emitcode("subb","a,acc");   
4521     }
4522     while (size--)
4523         pic16_aopPut(AOP(result),"a",offset++);
4524
4525 }
4526
4527 /*-----------------------------------------------------------------*/
4528 /* genDiv - generates code for division                            */
4529 /*-----------------------------------------------------------------*/
4530 static void genDiv (iCode *ic)
4531 {
4532     operand *left = IC_LEFT(ic);
4533     operand *right = IC_RIGHT(ic);
4534     operand *result= IC_RESULT(ic);   
4535
4536
4537         /* Division is a very lengthy algorithm, so it is better
4538          * to call support routines than inlining algorithm.
4539          * Division functions written here just in case someone
4540          * wants to inline and not use the support libraries -- VR */
4541
4542     FENTRY;
4543     
4544     /* assign the amsops */
4545     pic16_aopOp (left,ic,FALSE);
4546     pic16_aopOp (right,ic,FALSE);
4547     pic16_aopOp (result,ic,TRUE);
4548
4549     /* special cases first */
4550     /* both are bits */
4551     if (AOP_TYPE(left) == AOP_CRY &&
4552         AOP_TYPE(right)== AOP_CRY) {
4553         genDivbits(left,right,result);
4554         goto release ;
4555     }
4556
4557     /* if both are of size == 1 */
4558     if (AOP_SIZE(left) == 1 &&
4559         AOP_SIZE(right) == 1 ) {
4560         genDivOneByte(left,right,result);
4561         goto release ;
4562     }
4563
4564     /* should have been converted to function call */
4565     assert(0);
4566 release :
4567     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4568     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569     pic16_freeAsmop(result,NULL,ic,TRUE); 
4570 }
4571
4572 /*-----------------------------------------------------------------*/
4573 /* genModbits :- modulus of bits                                   */
4574 /*-----------------------------------------------------------------*/
4575 static void genModbits (operand *left, 
4576                         operand *right, 
4577                         operand *result)
4578 {
4579   char *l;
4580
4581     FENTRY;  
4582     
4583     werror(W_POSSBUG2, __FILE__, __LINE__);
4584     /* the result must be bit */    
4585     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4586     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4587
4588     MOVA(l);       
4589
4590     pic16_emitcode("div","ab");
4591     pic16_emitcode("mov","a,b");
4592     pic16_emitcode("rrc","a");
4593     pic16_aopPut(AOP(result),"c",0);
4594 }
4595
4596 /*-----------------------------------------------------------------*/
4597 /* genModOneByte : 8 bit modulus                                   */
4598 /*-----------------------------------------------------------------*/
4599 static void genModOneByte (operand *left,
4600                            operand *right,
4601                            operand *result)
4602 {
4603   sym_link *opetype = operandType(result);
4604   char *l ;
4605   symbol *lbl ;
4606
4607     FENTRY;
4608     werror(W_POSSBUG2, __FILE__, __LINE__);
4609
4610     /* signed or unsigned */
4611     if (SPEC_USIGN(opetype)) {
4612         /* unsigned is easy */
4613         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4614         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4615         MOVA(l);    
4616         pic16_emitcode("div","ab");
4617         pic16_aopPut(AOP(result),"b",0);
4618         return ;
4619     }
4620
4621     /* signed is a little bit more difficult */
4622
4623     /* save the signs of the operands */
4624     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4625     MOVA(l);
4626
4627     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4628     pic16_emitcode("push","acc"); /* save it on the stack */
4629
4630     /* now sign adjust for both left & right */
4631     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4632     MOVA(l);
4633
4634     lbl = newiTempLabel(NULL);
4635     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4636     pic16_emitcode("cpl","a");   
4637     pic16_emitcode("inc","a");
4638     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4639     pic16_emitcode("mov","b,a"); 
4640
4641     /* sign adjust left side */
4642     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4643     MOVA(l);
4644
4645     lbl = newiTempLabel(NULL);
4646     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4647     pic16_emitcode("cpl","a");   
4648     pic16_emitcode("inc","a");
4649     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4650
4651     /* now the multiplication */
4652     pic16_emitcode("div","ab");
4653     /* we are interested in the lower order
4654     only */
4655     lbl = newiTempLabel(NULL);
4656     pic16_emitcode("pop","acc");   
4657     /* if there was an over flow we don't 
4658     adjust the sign of the result */
4659     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4660     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4661     CLRC ;
4662     pic16_emitcode("clr","a");
4663     pic16_emitcode("subb","a,b");
4664     pic16_emitcode("mov","b,a");
4665     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4666
4667     /* now we are done */
4668     pic16_aopPut(AOP(result),"b",0);
4669
4670 }
4671
4672 /*-----------------------------------------------------------------*/
4673 /* genMod - generates code for division                            */
4674 /*-----------------------------------------------------------------*/
4675 static void genMod (iCode *ic)
4676 {
4677   operand *left = IC_LEFT(ic);
4678   operand *right = IC_RIGHT(ic);
4679   operand *result= IC_RESULT(ic);  
4680
4681     FENTRY;
4682     
4683     /* assign the amsops */
4684     pic16_aopOp (left,ic,FALSE);
4685     pic16_aopOp (right,ic,FALSE);
4686     pic16_aopOp (result,ic,TRUE);
4687
4688     /* special cases first */
4689     /* both are bits */
4690     if (AOP_TYPE(left) == AOP_CRY &&
4691         AOP_TYPE(right)== AOP_CRY) {
4692         genModbits(left,right,result);
4693         goto release ;
4694     }
4695
4696     /* if both are of size == 1 */
4697     if (AOP_SIZE(left) == 1 &&
4698         AOP_SIZE(right) == 1 ) {
4699         genModOneByte(left,right,result);
4700         goto release ;
4701     }
4702
4703     /* should have been converted to function call */
4704     assert(0);
4705
4706 release :
4707     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4708     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709     pic16_freeAsmop(result,NULL,ic,TRUE); 
4710 }
4711
4712 /*-----------------------------------------------------------------*/
4713 /* genIfxJump :- will create a jump depending on the ifx           */
4714 /*-----------------------------------------------------------------*/
4715 /*
4716   note: May need to add parameter to indicate when a variable is in bit space.
4717 */
4718 static void genIfxJump (iCode *ic, char *jval)
4719 {
4720   FENTRY;
4721   
4722     /* if true label then we jump if condition
4723     supplied is true */
4724     if ( IC_TRUE(ic) ) {
4725
4726         if(strcmp(jval,"a") == 0)
4727           emitSKPZ;
4728         else if (strcmp(jval,"c") == 0)
4729           emitSKPNC;
4730         else {
4731           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4732           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4733         }
4734
4735         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4736         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4737
4738     }
4739     else {
4740         /* false label is present */
4741         if(strcmp(jval,"a") == 0)
4742           emitSKPNZ;
4743         else if (strcmp(jval,"c") == 0)
4744           emitSKPC;
4745         else {
4746           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4747           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4748         }
4749
4750         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4751         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4752
4753     }
4754
4755
4756     /* mark the icode as generated */
4757     ic->generated = 1;
4758 }
4759
4760 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4761 {
4762   FENTRY;
4763   
4764     /* if true label then we jump if condition
4765     supplied is true */
4766     if ( IC_TRUE(ic) ) {
4767       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4768       pic16_emitpcode(POC_BTFSC, jop);
4769
4770       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4771       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4772
4773     } else {
4774       /* false label is present */
4775       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4776       pic16_emitpcode(POC_BTFSS, jop);
4777           
4778       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4779       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4780     }
4781
4782
4783     /* mark the icode as generated */
4784     ic->generated = 1;
4785 }
4786
4787 #if 0
4788 // not needed ATM
4789
4790 /*-----------------------------------------------------------------*/
4791 /* genSkip                                                         */
4792 /*-----------------------------------------------------------------*/
4793 static void genSkip(iCode *ifx,int status_bit)
4794 {
4795   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4796   if(!ifx)
4797     return;
4798
4799   if ( IC_TRUE(ifx) ) {
4800     switch(status_bit) {
4801     case 'z':
4802       emitSKPNZ;
4803       break;
4804
4805     case 'c':
4806       emitSKPNC;
4807       break;
4808
4809     case 'd':
4810       emitSKPDC;
4811       break;
4812
4813     }
4814
4815     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4816     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4817
4818   } else {
4819
4820     switch(status_bit) {
4821
4822     case 'z':
4823       emitSKPZ;
4824       break;
4825
4826     case 'c':
4827       emitSKPC;
4828       break;
4829
4830     case 'd':
4831       emitSKPDC;
4832       break;
4833     }
4834     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4835     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4836
4837   }
4838
4839 }
4840 #endif
4841
4842 /*-----------------------------------------------------------------*/
4843 /* genSkipc                                                        */
4844 /*-----------------------------------------------------------------*/
4845 static void genSkipc(resolvedIfx *rifx)
4846 {
4847   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4848   
4849   if(!rifx)
4850     return;
4851
4852   if(rifx->condition)
4853     emitSKPNC;
4854   else
4855     emitSKPC;
4856
4857   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4858   rifx->generated = 1;
4859 }
4860
4861 #if !(USE_SIMPLE_GENCMP)
4862 /*-----------------------------------------------------------------*/
4863 /* genSkipz2                                                       */
4864 /*-----------------------------------------------------------------*/
4865 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4866 {
4867   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4868   
4869   if(!rifx)
4870     return;
4871
4872   if( (rifx->condition ^ invert_condition) & 1)
4873     emitSKPZ;
4874   else
4875     emitSKPNZ;
4876
4877   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4878   rifx->generated = 1;
4879 }
4880 #endif
4881
4882 #if 0
4883 /*-----------------------------------------------------------------*/
4884 /* genSkipz                                                        */
4885 /*-----------------------------------------------------------------*/
4886 static void genSkipz(iCode *ifx, int condition)
4887 {
4888   if(!ifx)
4889     return;
4890
4891   if(condition)
4892     emitSKPNZ;
4893   else
4894     emitSKPZ;
4895
4896   if ( IC_TRUE(ifx) )
4897     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4898   else
4899     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4900
4901   if ( IC_TRUE(ifx) )
4902     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4903   else
4904     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4905
4906 }
4907 #endif
4908
4909 #if !(USE_SIMPLE_GENCMP)
4910 /*-----------------------------------------------------------------*/
4911 /* genSkipCond                                                     */
4912 /*-----------------------------------------------------------------*/
4913 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4914 {
4915   if(!rifx)
4916     return;
4917
4918   if(rifx->condition)
4919     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4920   else
4921     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4922
4923
4924   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4925   rifx->generated = 1;
4926 }
4927 #endif
4928
4929 #if 0
4930 /*-----------------------------------------------------------------*/
4931 /* genChkZeroes :- greater or less than comparison                 */
4932 /*     For each byte in a literal that is zero, inclusive or the   */
4933 /*     the corresponding byte in the operand with W                */
4934 /*     returns true if any of the bytes are zero                   */
4935 /*-----------------------------------------------------------------*/
4936 static int genChkZeroes(operand *op, int lit,  int size)
4937 {
4938
4939   int i;
4940   int flag =1;
4941
4942   while(size--) {
4943     i = (lit >> (size*8)) & 0xff;
4944
4945     if(i==0) {
4946       if(flag) 
4947         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4948       else
4949         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4950       flag = 0;
4951     }
4952   }
4953
4954   return (flag==0);
4955 }
4956 #endif
4957
4958
4959 /*-----------------------------------------------------------------*/
4960 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4961 /*                  aop (if it's NOT a literal) or from lit (if    */
4962 /*                  aop is a literal)                              */
4963 /*-----------------------------------------------------------------*/
4964 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4965   if (aop->type == AOP_LIT) {
4966     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4967   } else {
4968     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4969   }
4970 }
4971
4972 /*-----------------------------------------------------------------*/
4973 /* genCmp :- greater or less than comparison                       */
4974 /*-----------------------------------------------------------------*/
4975
4976 #if USE_SIMPLE_GENCMP           /* { */
4977
4978 /* genCmp performs a left < right comparison, stores
4979  * the outcome in result (if != NULL) and generates
4980  * control flow code for the ifx (if != NULL).
4981  *
4982  * This version leaves in sequences like
4983  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4984  * which should be optmized by the peephole
4985  * optimizer - RN 2005-01-01 */
4986 static void genCmp (operand *left,operand *right,
4987                     operand *result, iCode *ifx, int sign)
4988 {
4989   resolvedIfx rIfx;
4990   int size;
4991   int offs;
4992   symbol *templbl;
4993   operand *dummy;
4994   unsigned long lit;
4995   unsigned long mask;
4996   int performedLt;
4997
4998   FENTRY;
4999   
5000   assert (left && right);
5001   assert (AOP_SIZE(left) == AOP_SIZE(right));
5002
5003   size = AOP_SIZE(right) - 1;
5004   mask = (0x100UL << (size*8)) - 1;
5005   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5006   performedLt = 1;
5007   templbl = NULL;
5008   lit = 0;
5009   
5010   resolveIfx (&rIfx, ifx);
5011
5012   /* handle for special cases */
5013   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5014       return;
5015
5016   /**********************************************************************
5017    * handle bits - bit compares are promoted to int compares seemingly! *
5018    **********************************************************************/
5019 #if 0
5020   // THIS IS COMPLETELY UNTESTED!
5021   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5022     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5023     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5024     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5025
5026     emitSETC;
5027     // 1 < {0,1} is false --> clear C by skipping the next instruction
5028     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5029     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5030     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5031     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5032     emitCLRC; // only skipped for left=0 && right=1
5033
5034     goto correct_result_in_carry;
5035   } // if
5036 #endif
5037
5038   /*************************************************
5039    * make sure that left is register (or the like) *
5040    *************************************************/
5041   if (!isAOP_REGlike(left)) {
5042     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5043     assert (isAOP_LIT(left));
5044     assert (isAOP_REGlike(right));
5045     // swap left and right
5046     // left < right <==> right > left <==> (right >= left + 1)
5047     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5048
5049     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5050       // MAXVALUE < right? always false
5051       if (performedLt) emitCLRC; else emitSETC;
5052       goto correct_result_in_carry;
5053     } // if
5054
5055     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5056     // that's why we handled it above.
5057     lit++;
5058
5059     dummy = left;
5060     left = right;
5061     right = dummy;
5062
5063     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5064   } else if (isAOP_LIT(right)) {
5065     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5066   } // if
5067
5068   assert (isAOP_REGlike(left)); // left must be register or the like
5069   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5070
5071   /*************************************************
5072    * special cases go here                         *
5073    *************************************************/
5074
5075   if (isAOP_LIT(right)) {
5076     if (!sign) {
5077       // unsigned comparison to a literal
5078       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5079       if (lit == 0) {
5080         // unsigned left < 0? always false
5081         if (performedLt) emitCLRC; else emitSETC;
5082         goto correct_result_in_carry;
5083       }
5084     } else {
5085       // signed comparison to a literal
5086       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5087       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5088         // signed left < 0x80000000? always false
5089         if (performedLt) emitCLRC; else emitSETC;
5090         goto correct_result_in_carry;
5091       } else if (lit == 0) {
5092         // compare left < 0; set CARRY if SIGNBIT(left) is set
5093         if (performedLt) emitSETC; else emitCLRC;
5094         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5095         if (performedLt) emitCLRC; else emitSETC;
5096         goto correct_result_in_carry;
5097       }
5098     } // if (!sign)
5099   } // right is literal
5100
5101   /*************************************************
5102    * perform a general case comparison             *
5103    * make sure we get CARRY==1 <==> left >= right  *
5104    *************************************************/
5105   // compare most significant bytes
5106   //DEBUGpc ("comparing bytes at offset %d", size);
5107   if (!sign) {
5108     // unsigned comparison
5109     mov2w_regOrLit (AOP(right), lit, size);
5110     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5111   } else {
5112     // signed comparison
5113     // (add 2^n to both operands then perform an unsigned comparison)
5114     if (isAOP_LIT(right)) {
5115       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5116       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5117
5118       if (litbyte == 0x80) {
5119         // left >= 0x80 -- always true, but more bytes to come
5120         pic16_mov2w (AOP(left), size);
5121         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5122         emitSETC;
5123       } else {
5124         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5125         pic16_mov2w (AOP(left), size);
5126         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5128       } // if
5129     } else {
5130       /* using PRODL as a temporary register here */
5131       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133       pic16_mov2w (AOP(left), size);
5134       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135       pic16_emitpcode (POC_MOVWF, pctemp);
5136       pic16_mov2w (AOP(right), size);
5137       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138       pic16_emitpcode (POC_SUBFW, pctemp);
5139       //pic16_popReleaseTempReg(pctemp, 1);
5140     }
5141   } // if (!sign)
5142
5143   // compare remaining bytes (treat as unsigned case from above)
5144   templbl = newiTempLabel ( NULL );
5145   offs = size;
5146   while (offs--) {
5147     //DEBUGpc ("comparing bytes at offset %d", offs);
5148     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149     mov2w_regOrLit (AOP(right), lit, offs);
5150     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5151   } // while (offs)
5152   pic16_emitpLabel (templbl->key);
5153   goto result_in_carry;
5154
5155 result_in_carry:
5156   
5157   /****************************************************
5158    * now CARRY contains the result of the comparison: *
5159    * SUBWF sets CARRY iff                             *
5160    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5161    * (F=left, W=right)                                *
5162    ****************************************************/
5163
5164   if (performedLt) {
5165     if (result && AOP_TYPE(result) != AOP_CRY) {
5166       // value will be stored
5167       emitTOGC;
5168     } else {
5169       // value wil only be used in the following genSkipc()
5170       rIfx.condition ^= 1;
5171     }
5172   } // if
5173
5174 correct_result_in_carry:
5175
5176   // assign result to variable (if neccessary)
5177   if (result && AOP_TYPE(result) != AOP_CRY) {
5178     //DEBUGpc ("assign result");
5179     size = AOP_SIZE(result);
5180     while (size--) {
5181       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5182     } // while
5183     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5184   } // if (result)
5185
5186   // perform conditional jump
5187   if (ifx) {
5188     //DEBUGpc ("generate control flow");
5189     genSkipc (&rIfx);
5190     ifx->generated = 1;
5191   } // if
5192 }
5193
5194 #elif 1         /* } */
5195                 /* { */
5196       /* original code */
5197 static void genCmp (operand *left,operand *right,
5198                     operand *result, iCode *ifx, int sign)
5199 {
5200   int size; //, offset = 0 ;
5201   unsigned long lit = 0L,i = 0;
5202   resolvedIfx rFalseIfx;
5203   //  resolvedIfx rTrueIfx;
5204   symbol *truelbl;
5205   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206 /*
5207   if(ifx) {
5208     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5210   }
5211 */
5212
5213   FENTRY;
5214   
5215   resolveIfx(&rFalseIfx,ifx);
5216   truelbl  = newiTempLabel(NULL);
5217   size = max(AOP_SIZE(left),AOP_SIZE(right));
5218
5219   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5220
5221 #define _swapp
5222
5223   /* if literal is on the right then swap with left */
5224   if ((AOP_TYPE(right) == AOP_LIT)) {
5225     operand *tmp = right ;
5226     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5228 #ifdef _swapp
5229
5230     lit = (lit - 1) & mask;
5231     right = left;
5232     left = tmp;
5233     rFalseIfx.condition ^= 1;
5234 #endif
5235
5236   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5238   }
5239
5240
5241   //if(IC_TRUE(ifx) == NULL)
5242   /* if left & right are bit variables */
5243   if (AOP_TYPE(left) == AOP_CRY &&
5244       AOP_TYPE(right) == AOP_CRY ) {
5245     assert (0 && "bit variables used in genCmp");
5246     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5248   } else {
5249     /* subtract right from left if at the
5250        end the carry flag is set then we know that
5251        left is greater than right */
5252
5253     symbol *lbl  = newiTempLabel(NULL);
5254
5255 #if 0
5256         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5258 #endif
5259
5260 #ifndef _swapp
5261     if(AOP_TYPE(right) == AOP_LIT) {
5262
5263       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5264
5265       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5266
5267       /* special cases */
5268
5269       if(lit == 0) {
5270
5271         if(sign != 0) 
5272           genSkipCond(&rFalseIfx,left,size-1,7);
5273         else 
5274           /* no need to compare to 0...*/
5275           /* NOTE: this is a de-generate compare that most certainly 
5276            *       creates some dead code. */
5277           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5278
5279         if(ifx) ifx->generated = 1;
5280         return;
5281
5282       }
5283       size--;
5284
5285       if(size == 0) {
5286         //i = (lit >> (size*8)) & 0xff;
5287         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5288         
5289         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290
5291         i = ((0-lit) & 0xff);
5292         if(sign) {
5293           if( i == 0x81) { 
5294             /* lit is 0x7f, all signed chars are less than
5295              * this except for 0x7f itself */
5296             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297             genSkipz2(&rFalseIfx,0);
5298           } else {
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301             genSkipc(&rFalseIfx);
5302           }
5303
5304         } else {
5305           if(lit == 1) {
5306             genSkipz2(&rFalseIfx,1);
5307           } else {
5308             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309             genSkipc(&rFalseIfx);
5310           }
5311         }
5312
5313         if(ifx) ifx->generated = 1;
5314         return;
5315       }
5316
5317       /* chars are out of the way. now do ints and longs */
5318
5319
5320       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5321         
5322       /* special cases */
5323
5324       if(sign) {
5325
5326         if(lit == 0) {
5327           genSkipCond(&rFalseIfx,left,size,7);
5328           if(ifx) ifx->generated = 1;
5329           return;
5330         }
5331
5332         if(lit <0x100) {
5333           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334
5335           //rFalseIfx.condition ^= 1;
5336           //genSkipCond(&rFalseIfx,left,size,7);
5337           //rFalseIfx.condition ^= 1;
5338
5339           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340           if(rFalseIfx.condition)
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5342           else
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344
5345           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5348
5349           while(size > 1)
5350             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5351
5352           if(rFalseIfx.condition) {
5353             emitSKPZ;
5354             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5355
5356           } else {
5357             emitSKPNZ;
5358           }
5359
5360           genSkipc(&rFalseIfx);
5361           pic16_emitpLabel(truelbl->key);
5362           if(ifx) ifx->generated = 1;
5363           return;
5364
5365         }
5366
5367         if(size == 1) {
5368
5369           if( (lit & 0xff) == 0) {
5370             /* lower byte is zero */
5371             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372             i = ((lit >> 8) & 0xff) ^0x80;
5373             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376             genSkipc(&rFalseIfx);
5377
5378
5379             if(ifx) ifx->generated = 1;
5380             return;
5381
5382           }
5383         } else {
5384           /* Special cases for signed longs */
5385           if( (lit & 0xffffff) == 0) {
5386             /* lower byte is zero */
5387             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388             i = ((lit >> 8*3) & 0xff) ^0x80;
5389             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392             genSkipc(&rFalseIfx);
5393
5394
5395             if(ifx) ifx->generated = 1;
5396             return;
5397
5398           }
5399
5400         }
5401
5402
5403         if(lit & (0x80 << (size*8))) {
5404           /* lit is negative */
5405           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5406
5407           //genSkipCond(&rFalseIfx,left,size,7);
5408
5409           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5410
5411           if(rFalseIfx.condition)
5412             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5413           else
5414             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5415
5416
5417         } else {
5418           /* lit is positive */
5419           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421           if(rFalseIfx.condition)
5422             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5423           else
5424             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5425
5426         }
5427
5428         /*
5429           This works, but is only good for ints.
5430           It also requires a "known zero" register.
5431           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5434           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436           genSkipc(&rFalseIfx);
5437
5438           pic16_emitpLabel(truelbl->key);
5439           if(ifx) ifx->generated = 1;
5440           return;
5441         **/
5442           
5443         /* There are no more special cases, so perform a general compare */
5444   
5445         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447
5448         while(size--) {
5449
5450           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5451           emitSKPNZ;
5452           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5453         }
5454         //rFalseIfx.condition ^= 1;
5455         genSkipc(&rFalseIfx);
5456
5457         pic16_emitpLabel(truelbl->key);
5458
5459         if(ifx) ifx->generated = 1;
5460         return;
5461
5462
5463       }
5464
5465
5466       /* sign is out of the way. So now do an unsigned compare */
5467       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5468
5469
5470       /* General case - compare to an unsigned literal on the right.*/
5471
5472       i = (lit >> (size*8)) & 0xff;
5473       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5475       while(size--) {
5476         i = (lit >> (size*8)) & 0xff;
5477
5478         if(i) {
5479           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5480           emitSKPNZ;
5481           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5482         } else {
5483           /* this byte of the lit is zero, 
5484            *if it's not the last then OR in the variable */
5485           if(size)
5486             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487         }
5488       }
5489
5490
5491       pic16_emitpLabel(lbl->key);
5492 //      pic16_emitpLabel(truelbl->key);
5493       //if(emitFinalCheck)
5494       genSkipc(&rFalseIfx);
5495       if(sign)
5496         pic16_emitpLabel(truelbl->key);
5497
5498       if(ifx) ifx->generated = 1;
5499       return;
5500
5501
5502     }
5503 #endif  // _swapp
5504
5505     if(AOP_TYPE(left) == AOP_LIT) {
5506       //symbol *lbl = newiTempLabel(NULL);
5507
5508       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5509
5510
5511       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5512
5513       /* Special cases */
5514       if((lit == 0) && (sign == 0)){
5515
5516         size--;
5517         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5518         while(size) 
5519           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5520
5521         genSkipz2(&rFalseIfx,0);
5522         if(ifx) ifx->generated = 1;
5523         return;
5524       }
5525
5526       if(size==1) {
5527         /* Special cases */
5528         lit &= 0xff;
5529         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530           /* degenerate compare can never be true */
5531           if(rFalseIfx.condition == 0)
5532             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5533
5534           if(ifx) ifx->generated = 1;
5535           return;
5536         }
5537
5538         if(sign) {
5539           /* signed comparisons to a literal byte */
5540
5541           int lp1 = (lit+1) & 0xff;
5542
5543           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5544           switch (lp1) {
5545           case 0:
5546             rFalseIfx.condition ^= 1;
5547             genSkipCond(&rFalseIfx,right,0,7);
5548             break;
5549           case 0x7f:
5550             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552             genSkipz2(&rFalseIfx,1);
5553             break;
5554           default:
5555             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558             rFalseIfx.condition ^= 1;
5559             genSkipc(&rFalseIfx);
5560             break;
5561           }
5562         } else {
5563           /* unsigned comparisons to a literal byte */
5564
5565           switch(lit & 0xff ) {
5566           case 0:
5567             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568             genSkipz2(&rFalseIfx,0);
5569             break;
5570           case 0x7f:
5571             rFalseIfx.condition ^= 1;
5572             genSkipCond(&rFalseIfx,right,0,7);
5573             break;
5574
5575           default:
5576             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5579             rFalseIfx.condition ^= 1;
5580             if (AOP_TYPE(result) == AOP_CRY)
5581               genSkipc(&rFalseIfx);
5582             else {
5583               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5585             }         
5586             break;
5587           }
5588         }
5589
5590         if(ifx) ifx->generated = 1;
5591         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5592                 goto check_carry;
5593         return;
5594
5595       } else {
5596
5597         /* Size is greater than 1 */
5598
5599         if(sign) {
5600           int lp1 = lit+1;
5601
5602           size--;
5603
5604           if(lp1 == 0) {
5605             /* this means lit = 0xffffffff, or -1 */
5606
5607
5608             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609             rFalseIfx.condition ^= 1;
5610             genSkipCond(&rFalseIfx,right,size,7);
5611             if(ifx) ifx->generated = 1;
5612
5613             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5614               goto check_carry;
5615
5616             return;
5617           }
5618
5619           if(lit == 0) {
5620             int s = size;
5621
5622             if(rFalseIfx.condition) {
5623               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5625             }
5626
5627             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5628             while(size--)
5629               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5630
5631
5632             emitSKPZ;
5633             if(rFalseIfx.condition) {
5634               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5635               pic16_emitpLabel(truelbl->key);
5636             }else {
5637               rFalseIfx.condition ^= 1;
5638               genSkipCond(&rFalseIfx,right,s,7);
5639             }
5640
5641             if(ifx) ifx->generated = 1;
5642
5643             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5644               goto check_carry;
5645
5646             return;
5647           }
5648
5649           if((size == 1) &&  (0 == (lp1&0xff))) {
5650             /* lower byte of signed word is zero */
5651             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5652             i = ((lp1 >> 8) & 0xff) ^0x80;
5653             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5656
5657             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5658               emitTOGC;
5659               if(ifx) ifx->generated = 1;
5660               goto check_carry;
5661             } else {
5662               rFalseIfx.condition ^= 1;
5663               genSkipc(&rFalseIfx);
5664               if(ifx) ifx->generated = 1;
5665             }
5666
5667             return;
5668           }
5669
5670           if(lit & (0x80 << (size*8))) {
5671             /* Lit is less than zero */
5672             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5673             //rFalseIfx.condition ^= 1;
5674             //genSkipCond(&rFalseIfx,left,size,7);
5675             //rFalseIfx.condition ^= 1;
5676             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5678
5679             if(rFalseIfx.condition)
5680               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5681             else
5682               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5683
5684
5685           } else {
5686             /* Lit is greater than or equal to zero */
5687             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5688             //rFalseIfx.condition ^= 1;
5689             //genSkipCond(&rFalseIfx,right,size,7);
5690             //rFalseIfx.condition ^= 1;
5691
5692             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5694
5695             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696             if(rFalseIfx.condition)
5697               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5698             else
5699               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5700
5701           }
5702
5703           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705
5706           while(size--) {
5707
5708             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5709             emitSKPNZ;
5710             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5711           }
5712           rFalseIfx.condition ^= 1;
5713           //rFalseIfx.condition = 1;
5714           genSkipc(&rFalseIfx);
5715
5716           pic16_emitpLabel(truelbl->key);
5717
5718           if(ifx) ifx->generated = 1;
5719
5720
5721           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5722             goto check_carry;
5723
5724           return;
5725           // end of if (sign)
5726         } else {
5727
5728           /* compare word or long to an unsigned literal on the right.*/
5729
5730
5731           size--;
5732           if(lit < 0xff) {
5733             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5734             switch (lit) {
5735             case 0:
5736               break; /* handled above */
5737 /*
5738             case 0xff:
5739               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5740               while(size--)
5741                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742               genSkipz2(&rFalseIfx,0);
5743               break;
5744 */
5745             default:
5746               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5747               while(--size)
5748                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5749
5750               emitSKPZ;
5751               if(rFalseIfx.condition)
5752                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5753               else
5754                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5755
5756
5757               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5759
5760               rFalseIfx.condition ^= 1;
5761               genSkipc(&rFalseIfx);
5762             }
5763
5764             pic16_emitpLabel(truelbl->key);
5765
5766             if(ifx) ifx->generated = 1;
5767
5768             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769               goto check_carry;
5770
5771             return;
5772           }
5773
5774
5775           lit++;
5776           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777           i = (lit >> (size*8)) & 0xff;
5778
5779           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5781
5782           while(size--) {
5783             i = (lit >> (size*8)) & 0xff;
5784
5785             if(i) {
5786               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5787               emitSKPNZ;
5788               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5789             } else {
5790               /* this byte of the lit is zero, 
5791                * if it's not the last then OR in the variable */
5792               if(size)
5793                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794             }
5795           }
5796
5797
5798           pic16_emitpLabel(lbl->key);
5799
5800           rFalseIfx.condition ^= 1;
5801
5802           genSkipc(&rFalseIfx);
5803         }
5804
5805         if(sign)
5806           pic16_emitpLabel(truelbl->key);
5807         if(ifx) ifx->generated = 1;
5808
5809             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5810               goto check_carry;
5811
5812         return;
5813       }
5814     }
5815     /* Compare two variables */
5816
5817     DEBUGpic16_emitcode(";sign","%d",sign);
5818
5819     size--;
5820     if(sign) {
5821       /* Sigh. thus sucks... */
5822       if(size) {
5823         pCodeOp *pctemp;
5824         
5825         pctemp = pic16_popGetTempReg(1);
5826         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832         pic16_popReleaseTempReg(pctemp, 1);
5833       } else {
5834         /* Signed char comparison */
5835         /* Special thanks to Nikolai Golovchenko for this snippet */
5836         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5839         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5842
5843         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5844         genSkipc(&rFalseIfx);
5845           
5846         if(ifx) ifx->generated = 1;
5847
5848             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5849               goto check_carry;
5850
5851         return;
5852       }
5853
5854     } else {
5855
5856       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5858     }
5859
5860
5861     /* The rest of the bytes of a multi-byte compare */
5862     while (size) {
5863
5864       emitSKPZ;
5865       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5866       size--;
5867
5868       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870
5871
5872     }
5873
5874     pic16_emitpLabel(lbl->key);
5875
5876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5877     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5878         (AOP_TYPE(result) == AOP_REG)) {
5879       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5881     } else {
5882       genSkipc(&rFalseIfx);
5883     }         
5884     //genSkipc(&rFalseIfx);
5885     if(ifx) ifx->generated = 1;
5886
5887
5888             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889               goto check_carry;
5890
5891     return;
5892
5893   }
5894
5895 check_carry:
5896   if ((AOP_TYPE(result) != AOP_CRY) 
5897         && AOP_SIZE(result)) {
5898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899
5900     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5901
5902     pic16_outBitC(result);
5903   } else {
5904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5905     /* if the result is used in the next
5906        ifx conditional branch then generate
5907        code a little differently */
5908     if (ifx )
5909       genIfxJump (ifx,"c");
5910     else
5911       pic16_outBitC(result);
5912     /* leave the result in acc */
5913   }
5914
5915 }
5916
5917 #elif 0 /* VR version of genCmp() */    /* } else { */
5918
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921         operand *result, int offset, int invert_op)
5922 {
5923   /* add code here */
5924   
5925   /* check condition, > or < ?? */
5926   if(rIfx->condition != 0)invert_op ^= 1;
5927   
5928   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5929
5930   if(!ifx)invert_op ^= 1;
5931
5932   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5934   
5935   /* do selection */
5936   if(!invert_op)return POC_CPFSGT;
5937   else return POC_CPFSLT;
5938 }
5939
5940 static int compareAopfirstpass=1;
5941
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943             operand *oper, int offset, operand *result,
5944             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5945             symbol *tlbl)
5946 {
5947   int op;
5948   symbol *truelbl;
5949
5950   /* invert if there is a result to be loaded, in order to fit,
5951    * SETC/CLRC sequence */
5952   if(AOP_SIZE(result))invert_op ^= 1;
5953
5954 //  if(sign && !offset)invert_op ^= 1;
5955   
5956 //  if(sign)invert_op ^= 1;
5957   
5958   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5959
5960   if(AOP_SIZE(result) && compareAopfirstpass) {
5961     if(!ifx) {
5962       if(pcop2)
5963         pic16_emitpcode(POC_SETF, pcop2);
5964       else
5965         emitSETC;
5966     } else {
5967       if(pcop2)
5968         pic16_emitpcode(POC_CLRF, pcop2);
5969       else
5970         emitCLRC;
5971     }
5972   }
5973
5974   compareAopfirstpass = 0;
5975
5976       /* there is a bug when comparing operands with size > 1,
5977        * because higher bytes can be equal and test should be performed
5978        * to the next lower byte, current algorithm, considers operands
5979        * inequal in these cases! -- VR 20041107 */
5980
5981     
5982   if(pcop)
5983     pic16_emitpcode(op, pcop);
5984   else
5985     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5986
5987
5988   if((!sign || !offset) && AOP_SIZE(result)) {
5989     if(!ifx) {
5990       if(pcop2)
5991         pic16_emitpcode(POC_CLRF, pcop2);
5992         else
5993         emitCLRC;
5994     } else {
5995       if(pcop2)
5996         pic16_emitpcode(POC_SETF, pcop2);
5997       else
5998         emitSETC;
5999     }
6000     
6001     /* don't emit final branch (offset == 0) */
6002     if(offset) {
6003
6004       if(pcop2)
6005         pic16_emitpcode(POC_RRCF, pcop2);
6006
6007       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6008     }
6009   } else {
6010     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6013
6014       truelbl = newiTempLabel( NULL );
6015       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6018       else
6019         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020       pic16_emitpLabel(truelbl->key);
6021     } else {
6022       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023     }
6024   }
6025 }
6026
6027 static void genCmp (operand *left, operand *right,
6028                     operand *result, iCode *ifx, int sign)
6029 {
6030   int size, cmpop=1;
6031   long lit = 0L;
6032   resolvedIfx rFalseIfx;
6033   symbol *falselbl, *tlbl;
6034
6035     FENTRY;
6036     
6037     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6038
6039     resolveIfx(&rFalseIfx, ifx);
6040     size = max(AOP_SIZE(left), AOP_SIZE(right));
6041     
6042     /* if left & right are bit variables */
6043     if(AOP_TYPE(left) == AOP_CRY
6044       && AOP_TYPE(right) == AOP_CRY ) {
6045
6046         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6048         
6049         werror(W_POSSBUG2, __FILE__, __LINE__);
6050         exit(EXIT_FAILURE);
6051     }
6052     
6053     /* if literal is on the right then swap with left */
6054     if((AOP_TYPE(right) == AOP_LIT)) {
6055       operand *tmp = right ;
6056 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6057
6058         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6059
6060 //      lit = (lit - 1) & mask;
6061         right = left;
6062         left = tmp;
6063         rFalseIfx.condition ^= 1;               /* reverse compare */
6064     } else
6065     if ((AOP_TYPE(left) == AOP_LIT)) {
6066       /* float compares are handled by support functions */
6067       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6068     }
6069
6070     /* actual comparing algorithm */
6071 //    size = AOP_SIZE( right );
6072
6073     falselbl = newiTempLabel( NULL );
6074     if(AOP_TYPE(left) == AOP_LIT) {
6075       /* compare to literal */
6076       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6077       
6078       if(sign) {
6079         pCodeOp *pct, *pct2;
6080         symbol *tlbl1;
6081
6082         /* signed compare */
6083         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6084
6085         /* using PRODL:PRODH as a temporary register here */
6086         pct = pic16_popCopyReg(&pic16_pc_prodl);
6087         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6088         tlbl = newiTempLabel( NULL );
6089         
6090         /* first compare signs:
6091          *  a. if both are positive, compare just like unsigned
6092          *  b. if both are negative, invert cmpop, compare just like unsigned
6093          *  c. if different signs, determine the result directly */
6094
6095         size--;
6096
6097 #if 1
6098         /* { */
6099         tlbl1 = newiTempLabel( NULL );
6100 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6101
6102         if(lit > 0) {
6103
6104           /* literal is zero or positive:
6105            *  a. if carry is zero, too, continue compare,
6106            *  b. if carry is set, then continue depending on cmpop ^ condition:
6107            *    1. '<' return false (literal < variable),
6108            *    2. '>' return true (literal > variable) */
6109 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6110           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6111           
6112           
6113           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6115         } else 
6116         if(lit < 0) {
6117           
6118           /* literal is negative:
6119            *  a. if carry is set, too, continue compare,
6120            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6121            *    1. '<' return true (literal < variable),
6122            *    2. '>' return false (literal > variable) */
6123 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6124           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6125           
6126           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6128         }
6129 #if 1
6130         else {
6131           /* lit == 0 */
6132           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6133           
6134           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6135           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6136         }
6137 #endif
6138         
6139         
6140         pic16_emitpLabel( tlbl1->key );
6141 #endif  /* } */
6142
6143         compareAopfirstpass=1;
6144 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6145 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 //        pic16_emitpcode(POC_MOVWF, pct);
6147
6148 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6150 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6152
6153         /* generic case */        
6154           while( size-- ) {
6155 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6156 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6157 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6158 //            pic16_emitpcode(POC_MOVWF, pct);
6159
6160 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6161             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6162             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6163 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6165           }
6166         
6167         if(ifx)ifx->generated = 1;
6168
6169         if(AOP_SIZE(result)) {
6170           pic16_emitpLabel(tlbl->key);
6171           pic16_emitpLabel(falselbl->key);
6172           pic16_outBitOp( result, pct2 );
6173         } else {
6174           pic16_emitpLabel(tlbl->key);
6175         }
6176       } else {
6177
6178         /* unsigned compare */      
6179         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6180     
6181         compareAopfirstpass=1;
6182         while(size--) {
6183           
6184           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6185           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6186
6187         }
6188         if(ifx)ifx->generated = 1;
6189
6190         if(AOP_SIZE(result)) {
6191           pic16_emitpLabel(falselbl->key);
6192           pic16_outBitC( result );
6193         }
6194
6195       }
6196     } else {
6197       /* compare registers */
6198       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6199
6200
6201       if(sign) {
6202         pCodeOp *pct, *pct2;
6203         
6204         /* signed compare */
6205         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6206
6207         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6208         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6209         tlbl = newiTempLabel( NULL );
6210         
6211         compareAopfirstpass=1;
6212
6213         size--;
6214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6215 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217         pic16_emitpcode(POC_MOVWF, pct);
6218
6219         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6220 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6221         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6222
6223         /* WREG already holds left + 0x80 */
6224         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6225         
6226         while( size-- ) {
6227           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6228 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230           pic16_emitpcode(POC_MOVWF, pct);
6231                 
6232           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6233 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6234           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6235
6236           /* WREG already holds left + 0x80 */
6237           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6238 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6239         }
6240         
6241         if(ifx)ifx->generated = 1;
6242
6243         if(AOP_SIZE(result)) {
6244           pic16_emitpLabel(tlbl->key);
6245           pic16_emitpLabel(falselbl->key);
6246           pic16_outBitOp( result, pct2 );
6247         } else {
6248           pic16_emitpLabel(tlbl->key);
6249         }
6250
6251       } else {
6252         /* unsigned compare */      
6253         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6254
6255         compareAopfirstpass=1;
6256         while(size--) {
6257           
6258           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6259           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6260
6261         }
6262
6263         if(ifx)ifx->generated = 1;
6264         if(AOP_SIZE(result)) {
6265
6266           pic16_emitpLabel(falselbl->key);
6267           pic16_outBitC( result );
6268         }
6269
6270       }
6271     }
6272 }
6273
6274 #endif  /* } */
6275
6276
6277
6278 /*-----------------------------------------------------------------*/
6279 /* genCmpGt :- greater than comparison                             */
6280 /*-----------------------------------------------------------------*/
6281 static void genCmpGt (iCode *ic, iCode *ifx)
6282 {
6283   operand *left, *right, *result;
6284   sym_link *letype , *retype;
6285   int sign ;
6286
6287     FENTRY;
6288     
6289     left = IC_LEFT(ic);
6290     right= IC_RIGHT(ic);
6291     result = IC_RESULT(ic);
6292
6293     letype = getSpec(operandType(left));
6294     retype =getSpec(operandType(right));
6295     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6296     /* assign the amsops */
6297     pic16_aopOp (left,ic,FALSE);
6298     pic16_aopOp (right,ic,FALSE);
6299     pic16_aopOp (result,ic,TRUE);
6300
6301     genCmp(right, left, result, ifx, sign);
6302
6303     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6305     pic16_freeAsmop(result,NULL,ic,TRUE); 
6306 }
6307
6308 /*-----------------------------------------------------------------*/
6309 /* genCmpLt - less than comparisons                                */
6310 /*-----------------------------------------------------------------*/
6311 static void genCmpLt (iCode *ic, iCode *ifx)
6312 {
6313   operand *left, *right, *result;
6314   sym_link *letype , *retype;
6315   int sign ;
6316
6317     FENTRY;
6318
6319     left = IC_LEFT(ic);
6320     right= IC_RIGHT(ic);
6321     result = IC_RESULT(ic);
6322
6323     letype = getSpec(operandType(left));
6324     retype =getSpec(operandType(right));
6325     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6326
6327     /* assign the amsops */
6328     pic16_aopOp (left,ic,FALSE);
6329     pic16_aopOp (right,ic,FALSE);
6330     pic16_aopOp (result,ic,TRUE);
6331
6332     genCmp(left, right, result, ifx, sign);
6333
6334     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6336     pic16_freeAsmop(result,NULL,ic,TRUE); 
6337 }
6338
6339 #if 0
6340 // not needed ATM
6341 // FIXME reenable literal optimisation when the pic16 port is stable
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genc16bit2lit - compare a 16 bit value to a literal             */
6345 /*-----------------------------------------------------------------*/
6346 static void genc16bit2lit(operand *op, int lit, int offset)
6347 {
6348   int i;
6349
6350   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6351   if( (lit&0xff) == 0) 
6352     i=1;
6353   else
6354     i=0;
6355
6356   switch( BYTEofLONG(lit,i)) { 
6357   case 0:
6358     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359     break;
6360   case 1:
6361     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6362     break;
6363   case 0xff:
6364     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6365     break;
6366   default:
6367     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6368     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6369   }
6370
6371   i ^= 1;
6372
6373   switch( BYTEofLONG(lit,i)) { 
6374   case 0:
6375     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6376     break;
6377   case 1:
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6380     break;
6381   case 0xff:
6382     emitSKPNZ;
6383     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6384     break;
6385   default:
6386     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6387     emitSKPNZ;
6388     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6389
6390   }
6391
6392 }
6393 #endif
6394
6395 #if 0
6396 // not needed ATM
6397 /*-----------------------------------------------------------------*/
6398 /* gencjneshort - compare and jump if not equal                    */
6399 /*-----------------------------------------------------------------*/
6400 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6401 {
6402   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6403   int offset = 0;
6404   int res_offset = 0;  /* the result may be a different size then left or right */
6405   int res_size = AOP_SIZE(result);
6406   resolvedIfx rIfx;
6407   symbol *lbl, *lbl_done;
6408
6409   unsigned long lit = 0L;
6410   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6411
6412   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6413   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6414   if(result)
6415     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6416   resolveIfx(&rIfx,ifx);
6417   lbl =  newiTempLabel(NULL);
6418   lbl_done =  newiTempLabel(NULL);
6419
6420
6421   /* if the left side is a literal or 
6422      if the right is in a pointer register and left 
6423      is not */
6424   if ((AOP_TYPE(left) == AOP_LIT) || 
6425       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6426     operand *t = right;
6427     right = left;
6428     left = t;
6429   }
6430   if(AOP_TYPE(right) == AOP_LIT)
6431     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6432
6433   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6434     preserve_result = 1;
6435
6436   if(result && !preserve_result)
6437     {
6438       int i;
6439       for(i = 0; i < AOP_SIZE(result); i++)
6440         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6441     }
6442
6443
6444   /* if the right side is a literal then anything goes */
6445   if (AOP_TYPE(right) == AOP_LIT &&
6446       AOP_TYPE(left) != AOP_DIR ) {
6447     switch(size) {
6448     case 2:
6449       genc16bit2lit(left, lit, 0);
6450       emitSKPZ;
6451       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6452       break;
6453     default:
6454       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6455       while (size--) {
6456         if(lit & 0xff) {
6457           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6458           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6459         } else {
6460           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6461         }
6462
6463         emitSKPZ;
6464         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6465         offset++;
6466         if(res_offset < res_size-1)
6467           res_offset++;
6468         lit >>= 8;
6469       }
6470       break;
6471     }
6472   }
6473
6474   /* if the right side is in a register or in direct space or
6475      if the left is a pointer register & right is not */    
6476   else if (AOP_TYPE(right) == AOP_REG ||
6477            AOP_TYPE(right) == AOP_DIR || 
6478            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6479            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6480     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6481     int lbl_key = lbl->key;
6482
6483     if(result) {
6484       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6485       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6486     }else {
6487       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6488       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6489               __FUNCTION__,__LINE__);
6490       return;
6491     }
6492    
6493 /*     switch(size) { */
6494 /*     case 2: */
6495 /*       genc16bit2lit(left, lit, 0); */
6496 /*       emitSKPNZ; */
6497 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6498 /*       break; */
6499 /*     default: */
6500     while (size--) {
6501       int emit_skip=1;
6502       if((AOP_TYPE(left) == AOP_DIR) && 
6503          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6504
6505         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6507
6508       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6509             
6510         switch (lit & 0xff) {
6511         case 0:
6512           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513           break;
6514         case 1:
6515           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6516           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6518           emit_skip=0;
6519           break;
6520         case 0xff:
6521           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6523           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6524           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6525           emit_skip=0;
6526           break;
6527         default:
6528           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6529           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6530         }
6531         lit >>= 8;
6532
6533       } else {
6534         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6535       }
6536       if(emit_skip) {
6537         if(AOP_TYPE(result) == AOP_CRY) {
6538           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6539           if(rIfx.condition)
6540             emitSKPNZ;
6541           else
6542             emitSKPZ;
6543           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6544         } else {
6545           /* fix me. probably need to check result size too */
6546           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6547           if(rIfx.condition)
6548             emitSKPZ;
6549           else
6550             emitSKPNZ;
6551           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6552           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6553         }
6554         if(ifx)
6555           ifx->generated=1;
6556       }
6557       emit_skip++;
6558       offset++;
6559       if(res_offset < res_size-1)
6560         res_offset++;
6561     }
6562 /*       break; */
6563 /*     } */
6564   } else if(AOP_TYPE(right) == AOP_REG &&
6565             AOP_TYPE(left) != AOP_DIR){
6566
6567     while(size--) {
6568       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6569       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6570       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6571       if(rIfx.condition)
6572         emitSKPNZ;
6573       else
6574         emitSKPZ;
6575       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6576       offset++;
6577       if(res_offset < res_size-1)
6578         res_offset++;
6579     }
6580       
6581   }else{
6582     /* right is a pointer reg need both a & b */
6583     while(size--) {
6584       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6585       if(strcmp(l,"b"))
6586         pic16_emitcode("mov","b,%s",l);
6587       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6589       offset++;
6590     }
6591   }
6592
6593   if(result && preserve_result)
6594     {
6595       int i;
6596       for(i = 0; i < AOP_SIZE(result); i++)
6597         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6598     }
6599
6600   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6601
6602   if(result && preserve_result)
6603     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6604
6605   if(!rIfx.condition)
6606     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6607
6608   pic16_emitpLabel(lbl->key);
6609
6610   if(result && preserve_result)
6611     {
6612       int i;
6613       for(i = 0; i < AOP_SIZE(result); i++)
6614         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6615
6616       pic16_emitpLabel(lbl_done->key);
6617    }
6618
6619   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6620
6621   if(ifx)
6622     ifx->generated = 1;
6623 }
6624 #endif
6625
6626 #if 0
6627 /*-----------------------------------------------------------------*/
6628 /* gencjne - compare and jump if not equal                         */
6629 /*-----------------------------------------------------------------*/
6630 static void gencjne(operand *left, operand *right, iCode *ifx)
6631 {
6632     symbol *tlbl  = newiTempLabel(NULL);
6633
6634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6635     gencjneshort(left, right, lbl);
6636
6637     pic16_emitcode("mov","a,%s",one);
6638     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6639     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6640     pic16_emitcode("clr","a");
6641     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6642
6643     pic16_emitpLabel(lbl->key);
6644     pic16_emitpLabel(tlbl->key);
6645
6646 }
6647 #endif
6648
6649
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitOp - check if operand has to be treated as literal        */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitOp(operand *op)
6654 {
6655   return ((AOP_TYPE(op) == AOP_LIT)
6656       || ( (AOP_TYPE(op) == AOP_PCODE)
6657           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6658               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6659 }
6660
6661 /*-----------------------------------------------------------------*/
6662 /* is_LitAOp - check if operand has to be treated as literal        */
6663 /*-----------------------------------------------------------------*/
6664 static bool is_LitAOp(asmop *aop)
6665 {
6666   return ((aop->type == AOP_LIT)
6667       || ( (aop->type == AOP_PCODE)
6668           && ( (aop->aopu.pcop->type == PO_LITERAL)
6669               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6670 }
6671
6672
6673
6674 /*-----------------------------------------------------------------*/
6675 /* genCmpEq - generates code for equal to                          */
6676 /*-----------------------------------------------------------------*/
6677 static void genCmpEq (iCode *ic, iCode *ifx)
6678 {
6679   operand *left, *right, *result;
6680   symbol *falselbl = newiTempLabel(NULL);
6681   symbol *donelbl = newiTempLabel(NULL);
6682
6683   int preserve_result = 0;
6684   int generate_result = 0;
6685   int i=0;
6686   unsigned long lit = -1;
6687
6688   FENTRY;
6689   
6690   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6691   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6692   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6693  
6694   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6695
6696   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6697     {
6698       werror(W_POSSBUG2, __FILE__, __LINE__);
6699       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6700       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6701       goto release;
6702     }
6703
6704   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6705     {
6706       operand *tmp = right ;
6707       right = left;
6708       left = tmp;
6709     }
6710
6711   if (AOP_TYPE(right) == AOP_LIT) {
6712     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6713   }
6714
6715   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6716     preserve_result = 1;
6717
6718   if(result && AOP_SIZE(result))
6719     generate_result = 1;
6720
6721   if(generate_result && !preserve_result)
6722     {
6723       for(i = 0; i < AOP_SIZE(result); i++)
6724         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6725     }
6726
6727   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6728   for(i=0; i < AOP_SIZE(left); i++)
6729     {
6730       if(AOP_TYPE(left) != AOP_ACC)
6731         {
6732           if(is_LitOp(left))
6733             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6734           else
6735             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6736         }
6737       if(is_LitOp(right)) {
6738         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6739           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6740         }
6741       } else
6742         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6743
6744       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6745     }
6746
6747   // result == true
6748
6749   if(generate_result && preserve_result)
6750     {
6751       for(i = 0; i < AOP_SIZE(result); i++)
6752         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6753     }
6754
6755   if(generate_result)
6756     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6757
6758   if(generate_result && preserve_result)
6759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6760
6761   if(ifx && IC_TRUE(ifx))
6762     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6763
6764   if(ifx && IC_FALSE(ifx))
6765     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6766
6767   pic16_emitpLabel(falselbl->key);
6768
6769   // result == false
6770
6771   if(ifx && IC_FALSE(ifx))
6772     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6773
6774   if(generate_result && preserve_result)
6775     {
6776       for(i = 0; i < AOP_SIZE(result); i++)
6777         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6778     }
6779
6780   pic16_emitpLabel(donelbl->key);
6781
6782   if(ifx)
6783     ifx->generated = 1;
6784
6785 release:
6786   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6787   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6788   pic16_freeAsmop(result,NULL,ic,TRUE);
6789
6790 }
6791
6792
6793 #if 0
6794 // old version kept for reference
6795
6796 /*-----------------------------------------------------------------*/
6797 /* genCmpEq - generates code for equal to                          */
6798 /*-----------------------------------------------------------------*/
6799 static void genCmpEq (iCode *ic, iCode *ifx)
6800 {
6801     operand *left, *right, *result;
6802     unsigned long lit = 0L;
6803     int size,offset=0;
6804     symbol *falselbl  = newiTempLabel(NULL);
6805
6806
6807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6808
6809     if(ifx)
6810       DEBUGpic16_emitcode ("; ifx is non-null","");
6811     else
6812       DEBUGpic16_emitcode ("; ifx is null","");
6813
6814     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6815     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6816     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6817
6818     size = max(AOP_SIZE(left),AOP_SIZE(right));
6819
6820     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6821
6822     /* if literal, literal on the right or 
6823     if the right is in a pointer register and left 
6824     is not */
6825     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6826         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6827       operand *tmp = right ;
6828       right = left;
6829       left = tmp;
6830     }
6831
6832
6833     if(ifx && !AOP_SIZE(result)){
6834         symbol *tlbl;
6835         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6836         /* if they are both bit variables */
6837         if (AOP_TYPE(left) == AOP_CRY &&
6838             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6839                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6840             if(AOP_TYPE(right) == AOP_LIT){
6841                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6842                 if(lit == 0L){
6843                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844                     pic16_emitcode("cpl","c");
6845                 } else if(lit == 1L) {
6846                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6847                 } else {
6848                     pic16_emitcode("clr","c");
6849                 }
6850                 /* AOP_TYPE(right) == AOP_CRY */
6851             } else {
6852                 symbol *lbl = newiTempLabel(NULL);
6853                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6854                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6855                 pic16_emitcode("cpl","c");
6856                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6857             }
6858             /* if true label then we jump if condition
6859             supplied is true */
6860             tlbl = newiTempLabel(NULL);
6861             if ( IC_TRUE(ifx) ) {
6862                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6863                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6864             } else {
6865                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6866                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6867             }
6868             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6869
6870                 {
6871                 /* left and right are both bit variables, result is carry */
6872                         resolvedIfx rIfx;
6873               
6874                         resolveIfx(&rIfx,ifx);
6875
6876                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6877                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6878                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6879                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6880                         genSkipz2(&rIfx,0);
6881                 }
6882         } else {
6883
6884                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6885
6886                         /* They're not both bit variables. Is the right a literal? */
6887                         if(AOP_TYPE(right) == AOP_LIT) {
6888                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6889             
6890                         switch(size) {
6891
6892                                 case 1:
6893                                         switch(lit & 0xff) {
6894                                                 case 1:
6895                                                                 if ( IC_TRUE(ifx) ) {
6896                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6897                                                                         emitSKPNZ;
6898                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6899                                                                 } else {
6900                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6901                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6902                                                                 }
6903                                                                 break;
6904                                                 case 0xff:
6905                                                                 if ( IC_TRUE(ifx) ) {
6906                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6907                                                                         emitSKPNZ;
6908                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6909                                                                 } else {
6910                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6911                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6912                                                                 }
6913                                                                 break;
6914                                                 default:
6915                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6916                                                                 if(lit)
6917                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6918                                                                 genSkip(ifx,'z');
6919                                         } // switch lit
6920
6921
6922                                         /* end of size == 1 */
6923                                         break;
6924               
6925                                 case 2:
6926                                         genc16bit2lit(left,lit,offset);
6927                                         genSkip(ifx,'z');
6928                                         break;
6929                                         /* end of size == 2 */
6930
6931                                 default:
6932                                         /* size is 4 */
6933                                         if(lit==0) {
6934                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6935                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6936                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6937                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6938                                                 genSkip(ifx,'z');
6939                                         } else {
6940                                                 /* search for patterns that can be optimized */
6941
6942                                                 genc16bit2lit(left,lit,0);
6943                                                 lit >>= 16;
6944                                                 if(lit) {
6945                                                                 if(IC_TRUE(ifx))
6946                                                                 emitSKPZ; // if hi word unequal
6947                                                                 else
6948                                                                 emitSKPNZ; // if hi word equal
6949                                                                 // fail early
6950                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6951                                                         genc16bit2lit(left,lit,2);
6952                                                         genSkip(ifx,'z');
6953                                                 } else {
6954                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6955                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6956                                                         genSkip(ifx,'z');
6957                                                 }
6958                                         }
6959                                                 pic16_emitpLabel(falselbl->key);
6960                                                 break;
6961
6962                         } // switch size
6963           
6964                         ifx->generated = 1;
6965                         goto release ;
6966             
6967
6968           } else if(AOP_TYPE(right) == AOP_CRY ) {
6969             /* we know the left is not a bit, but that the right is */
6970             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6971             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6972                       pic16_popGet(AOP(right),offset));
6973             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6974
6975             /* if the two are equal, then W will be 0 and the Z bit is set
6976              * we could test Z now, or go ahead and check the high order bytes if
6977              * the variable we're comparing is larger than a byte. */
6978
6979             while(--size)
6980               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6981
6982             if ( IC_TRUE(ifx) ) {
6983               emitSKPNZ;
6984               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6985               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6986             } else {
6987               emitSKPZ;
6988               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6989               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6990             }
6991
6992           } else {
6993             /* They're both variables that are larger than bits */
6994             int s = size;
6995
6996             tlbl = newiTempLabel(NULL);
6997
6998             while(size--) {
6999               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7000               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7001
7002               if ( IC_TRUE(ifx) ) {
7003                 if(size) {
7004                   emitSKPZ;
7005                 
7006                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7007
7008                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7009                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7010                 } else {
7011                   emitSKPNZ;
7012
7013                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7014
7015
7016                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7017                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7018                 }
7019               } else {
7020                 emitSKPZ;
7021
7022                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7023
7024                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7025                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7026               }
7027               offset++;
7028             }
7029             if(s>1 && IC_TRUE(ifx)) {
7030               pic16_emitpLabel(tlbl->key);
7031               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7032             }
7033           }
7034         }
7035         /* mark the icode as generated */
7036         ifx->generated = 1;
7037         goto release ;
7038     }
7039
7040     /* if they are both bit variables */
7041     if (AOP_TYPE(left) == AOP_CRY &&
7042         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7043         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7044         if(AOP_TYPE(right) == AOP_LIT){
7045             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7046             if(lit == 0L){
7047                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048                 pic16_emitcode("cpl","c");
7049             } else if(lit == 1L) {
7050                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7051             } else {
7052                 pic16_emitcode("clr","c");
7053             }
7054             /* AOP_TYPE(right) == AOP_CRY */
7055         } else {
7056             symbol *lbl = newiTempLabel(NULL);
7057             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7058             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7059             pic16_emitcode("cpl","c");
7060             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7061         }
7062         /* c = 1 if egal */
7063         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7064             pic16_outBitC(result);
7065             goto release ;
7066         }
7067         if (ifx) {
7068             genIfxJump (ifx,"c");
7069             goto release ;
7070         }
7071         /* if the result is used in an arithmetic operation
7072         then put the result in place */
7073         pic16_outBitC(result);
7074     } else {
7075       
7076       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7077       gencjne(left,right,result,ifx);
7078 /*
7079       if(ifx) 
7080         gencjne(left,right,newiTempLabel(NULL));
7081       else {
7082         if(IC_TRUE(ifx)->key)
7083           gencjne(left,right,IC_TRUE(ifx)->key);
7084         else
7085           gencjne(left,right,IC_FALSE(ifx)->key);
7086         ifx->generated = 1;
7087         goto release ;
7088       }
7089       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7090         pic16_aopPut(AOP(result),"a",0);
7091         goto release ;
7092       }
7093
7094       if (ifx) {
7095         genIfxJump (ifx,"a");
7096         goto release ;
7097       }
7098 */
7099       /* if the result is used in an arithmetic operation
7100          then put the result in place */
7101 /*
7102       if (AOP_TYPE(result) != AOP_CRY) 
7103         pic16_outAcc(result);
7104 */
7105       /* leave the result in acc */
7106     }
7107
7108 release:
7109     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7110     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7111     pic16_freeAsmop(result,NULL,ic,TRUE);
7112 }
7113 #endif
7114
7115 /*-----------------------------------------------------------------*/
7116 /* ifxForOp - returns the icode containing the ifx for operand     */
7117 /*-----------------------------------------------------------------*/
7118 static iCode *ifxForOp ( operand *op, iCode *ic )
7119 {
7120   FENTRY2;
7121
7122     /* if true symbol then needs to be assigned */
7123     if (IS_TRUE_SYMOP(op))
7124         return NULL ;
7125
7126     /* if this has register type condition and
7127     the next instruction is ifx with the same operand
7128     and live to of the operand is upto the ifx only then */
7129     if (ic->next
7130         && ic->next->op == IFX
7131         && IC_COND(ic->next)->key == op->key
7132         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7133         ) {
7134                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7135           return ic->next;
7136     }
7137
7138     /*
7139     if (ic->next &&
7140         ic->next->op == IFX &&
7141         IC_COND(ic->next)->key == op->key) {
7142       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7143       return ic->next;
7144     }
7145     */
7146
7147     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7148     if (ic->next &&
7149         ic->next->op == IFX)
7150       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7151
7152     if (ic->next &&
7153         ic->next->op == IFX &&
7154         IC_COND(ic->next)->key == op->key) {
7155       DEBUGpic16_emitcode ("; "," key is okay");
7156       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7157                            OP_SYMBOL(op)->liveTo,
7158                            ic->next->seq);
7159     }
7160
7161 #if 0
7162     /* the code below is completely untested
7163      * it just allows ulong2fs.c compile -- VR */
7164          
7165     ic = ic->next;
7166     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7167                                         __FILE__, __FUNCTION__, __LINE__);
7168         
7169     /* if this has register type condition and
7170     the next instruction is ifx with the same operand
7171     and live to of the operand is upto the ifx only then */
7172     if (ic->next &&
7173         ic->next->op == IFX &&
7174         IC_COND(ic->next)->key == op->key &&
7175         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7176         return ic->next;
7177
7178     if (ic->next &&
7179         ic->next->op == IFX &&
7180         IC_COND(ic->next)->key == op->key) {
7181       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7182       return ic->next;
7183     }
7184
7185     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7186                                         __FILE__, __FUNCTION__, __LINE__);
7187
7188 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7189 #endif
7190
7191     return NULL;
7192 }
7193 /*-----------------------------------------------------------------*/
7194 /* genAndOp - for && operation                                     */
7195 /*-----------------------------------------------------------------*/
7196 static void genAndOp (iCode *ic)
7197 {
7198   operand *left,*right, *result;
7199 /*     symbol *tlbl; */
7200
7201     FENTRY;
7202
7203     /* note here that && operations that are in an
7204     if statement are taken away by backPatchLabels
7205     only those used in arthmetic operations remain */
7206     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7207     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7208     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7209
7210     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7211
7212     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7213     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7214     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7215
7216     /* if both are bit variables */
7217 /*     if (AOP_TYPE(left) == AOP_CRY && */
7218 /*         AOP_TYPE(right) == AOP_CRY ) { */
7219 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7220 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7221 /*         pic16_outBitC(result); */
7222 /*     } else { */
7223 /*         tlbl = newiTempLabel(NULL); */
7224 /*         pic16_toBoolean(left);     */
7225 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7226 /*         pic16_toBoolean(right); */
7227 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7228 /*         pic16_outBitAcc(result); */
7229 /*     } */
7230
7231     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7232     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7233     pic16_freeAsmop(result,NULL,ic,TRUE);
7234 }
7235
7236
7237 /*-----------------------------------------------------------------*/
7238 /* genOrOp - for || operation                                      */
7239 /*-----------------------------------------------------------------*/
7240 /*
7241   tsd pic port -
7242   modified this code, but it doesn't appear to ever get called
7243 */
7244
7245 static void genOrOp (iCode *ic)
7246 {
7247   operand *left,*right, *result;
7248   symbol *tlbl;
7249
7250     FENTRY;  
7251
7252   /* note here that || operations that are in an
7253     if statement are taken away by backPatchLabels
7254     only those used in arthmetic operations remain */
7255     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7256     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7257     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7258
7259     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7260
7261     /* if both are bit variables */
7262     if (AOP_TYPE(left) == AOP_CRY &&
7263         AOP_TYPE(right) == AOP_CRY ) {
7264       pic16_emitcode("clrc","");
7265       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7266                AOP(left)->aopu.aop_dir,
7267                AOP(left)->aopu.aop_dir);
7268       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7269                AOP(right)->aopu.aop_dir,
7270                AOP(right)->aopu.aop_dir);
7271       pic16_emitcode("setc","");
7272
7273     } else {
7274         tlbl = newiTempLabel(NULL);
7275         pic16_toBoolean(left);
7276         emitSKPZ;
7277         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7278         pic16_toBoolean(right);
7279         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7280
7281         pic16_outBitAcc(result);
7282     }
7283
7284     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7285     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7286     pic16_freeAsmop(result,NULL,ic,TRUE);            
7287 }
7288
7289 /*-----------------------------------------------------------------*/
7290 /* isLiteralBit - test if lit == 2^n                               */
7291 /*-----------------------------------------------------------------*/
7292 static int isLiteralBit(unsigned long lit)
7293 {
7294     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7295     0x100L,0x200L,0x400L,0x800L,
7296     0x1000L,0x2000L,0x4000L,0x8000L,
7297     0x10000L,0x20000L,0x40000L,0x80000L,
7298     0x100000L,0x200000L,0x400000L,0x800000L,
7299     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7300     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7301     int idx;
7302     
7303     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7304     for(idx = 0; idx < 32; idx++)
7305         if(lit == pw[idx])
7306             return idx+1;
7307     return 0;
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* continueIfTrue -                                                */
7312 /*-----------------------------------------------------------------*/
7313 static void continueIfTrue (iCode *ic)
7314 {
7315   FENTRY;
7316   if(IC_TRUE(ic))
7317     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7318   ic->generated = 1;
7319 }
7320
7321 /*-----------------------------------------------------------------*/
7322 /* jmpIfTrue -                                                     */
7323 /*-----------------------------------------------------------------*/
7324 static void jumpIfTrue (iCode *ic)
7325 {
7326   FENTRY;
7327   if(!IC_TRUE(ic))
7328     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7329   ic->generated = 1;
7330 }
7331
7332 /*-----------------------------------------------------------------*/
7333 /* jmpTrueOrFalse -                                                */
7334 /*-----------------------------------------------------------------*/
7335 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7336 {
7337   // ugly but optimized by peephole
7338   FENTRY;
7339   if(IC_TRUE(ic)){
7340     symbol *nlbl = newiTempLabel(NULL);
7341       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7342       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7343       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7344       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7345   } else {
7346     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7347     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7348   }
7349   ic->generated = 1;
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* genAnd  - code for and                                          */
7354 /*-----------------------------------------------------------------*/
7355 static void genAnd (iCode *ic, iCode *ifx)
7356 {
7357   operand *left, *right, *result;
7358   int size, offset=0;  
7359   unsigned long lit = 0L;
7360   int bytelit = 0;
7361   resolvedIfx rIfx;
7362
7363     FENTRY;
7364     
7365   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7366   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7367   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7368
7369   resolveIfx(&rIfx,ifx);
7370
7371   /* if left is a literal & right is not then exchange them */
7372   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7373       AOP_NEEDSACC(left)) {
7374     operand *tmp = right ;
7375     right = left;
7376     left = tmp;
7377   }
7378
7379   /* if result = right then exchange them */
7380   if(pic16_sameRegs(AOP(result),AOP(right))){
7381     operand *tmp = right ;
7382     right = left;
7383     left = tmp;
7384   }
7385
7386   /* if right is bit then exchange them */
7387   if (AOP_TYPE(right) == AOP_CRY &&
7388       AOP_TYPE(left) != AOP_CRY){
7389     operand *tmp = right ;
7390     right = left;
7391     left = tmp;
7392   }
7393   if(AOP_TYPE(right) == AOP_LIT)
7394     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7395
7396   size = AOP_SIZE(result);
7397
7398   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7399
7400   // if(bit & yy)
7401   // result = bit & yy;
7402   if (AOP_TYPE(left) == AOP_CRY){
7403     // c = bit & literal;
7404     if(AOP_TYPE(right) == AOP_LIT){
7405       if(lit & 1) {
7406         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7407           // no change
7408           goto release;
7409         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7410       } else {
7411         // bit(result) = 0;
7412         if(size && (AOP_TYPE(result) == AOP_CRY)){
7413           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7414           goto release;
7415         }
7416         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7417           jumpIfTrue(ifx);
7418           goto release;
7419         }
7420         pic16_emitcode("clr","c");
7421       }
7422     } else {
7423       if (AOP_TYPE(right) == AOP_CRY){
7424         // c = bit & bit;
7425         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7426         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427       } else {
7428         // c = bit & val;
7429         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7430         // c = lsb
7431         pic16_emitcode("rrc","a");
7432         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7433       }
7434     }
7435     // bit = c
7436     // val = c
7437     if(size)
7438       pic16_outBitC(result);
7439     // if(bit & ...)
7440     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7441       genIfxJump(ifx, "c");           
7442     goto release ;
7443   }
7444
7445   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7446   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7447   if((AOP_TYPE(right) == AOP_LIT) &&
7448      (AOP_TYPE(result) == AOP_CRY) &&
7449      (AOP_TYPE(left) != AOP_CRY)){
7450     int posbit = isLiteralBit(lit);
7451     /* left &  2^n */
7452     if(posbit){
7453       posbit--;
7454       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7455       // bit = left & 2^n
7456       if(size)
7457         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7458       // if(left &  2^n)
7459       else{
7460         if(ifx){
7461 /*
7462           if(IC_TRUE(ifx)) {
7463             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7464             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7465           } else {
7466             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7467             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7468           }
7469 */
7470         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7471         size = AOP_SIZE(left);
7472
7473         {
7474           int bp = posbit, ofs=0;
7475           
7476             while(bp > 7) {
7477               bp -= 8;
7478               ofs++;
7479             }
7480
7481           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7482                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7483
7484         }
7485 /*
7486           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7487                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7488 */
7489           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7490           
7491           ifx->generated = 1;
7492         }
7493         goto release;
7494       }
7495     } else {
7496       symbol *tlbl = newiTempLabel(NULL);
7497       int sizel = AOP_SIZE(left);
7498
7499       if(size)
7500         emitSETC;
7501
7502       while(sizel--) {
7503         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7504
7505           /* patch provided by Aaron Colwell */
7506           if((posbit = isLiteralBit(bytelit)) != 0) {
7507               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7508                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7509                                                 (posbit-1),0, PO_GPR_REGISTER));
7510
7511               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7512 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7513           } else {
7514               if (bytelit == 0xff) {
7515                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7516                    * a peephole could optimize it out -- VR */
7517                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518               } else {
7519                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7520                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7521               }
7522
7523               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7524                             pic16_popGetLabel(tlbl->key));
7525           }
7526         
7527 #if 0
7528           /* old code, left here for reference -- VR 09/2004 */
7529           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7530           // byte ==  2^n ?
7531           if((posbit = isLiteralBit(bytelit)) != 0)
7532             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7533           else{
7534             if(bytelit != 0x0FFL)
7535               pic16_emitcode("anl","a,%s",
7536                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7537             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7538           }
7539 #endif
7540         }
7541         offset++;
7542       }
7543       // bit = left & literal
7544       if(size) {
7545         emitCLRC;
7546         pic16_emitpLabel(tlbl->key);
7547       }
7548       // if(left & literal)
7549       else {
7550         if(ifx) {
7551           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7552           ifx->generated = 1;
7553         }
7554         pic16_emitpLabel(tlbl->key);
7555         goto release;
7556       }
7557     }
7558
7559     pic16_outBitC(result);
7560     goto release ;
7561   }
7562
7563   /* if left is same as result */
7564   if(pic16_sameRegs(AOP(result),AOP(left))){
7565     int know_W = -1;
7566     for(;size--; offset++,lit>>=8) {
7567       if(AOP_TYPE(right) == AOP_LIT){
7568         switch(lit & 0xff) {
7569         case 0x00:
7570           /*  and'ing with 0 has clears the result */
7571 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7573           break;
7574         case 0xff:
7575           /* and'ing with 0xff is a nop when the result and left are the same */
7576           break;
7577
7578         default:
7579           {
7580             int p = pic16_my_powof2( (~lit) & 0xff );
7581             if(p>=0) {
7582               /* only one bit is set in the literal, so use a bcf instruction */
7583 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7584               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7585
7586             } else {
7587               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7588               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7589               if(know_W != (lit&0xff))
7590                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7591               know_W = lit &0xff;
7592               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7593             }
7594           }    
7595         }
7596       } else {
7597         if (AOP_TYPE(left) == AOP_ACC) {
7598           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7599         } else {                    
7600           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7601           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7602
7603         }
7604       }
7605     }
7606
7607   } else {
7608     // left & result in different registers
7609     if(AOP_TYPE(result) == AOP_CRY){
7610       // result = bit
7611       // if(size), result in bit
7612       // if(!size && ifx), conditional oper: if(left & right)
7613       symbol *tlbl = newiTempLabel(NULL);
7614       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7615       if(size)
7616         pic16_emitcode("setb","c");
7617       while(sizer--){
7618         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7619         pic16_emitcode("anl","a,%s",
7620                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7621         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7622         offset++;
7623       }
7624       if(size){
7625         CLRC;
7626         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7627         pic16_outBitC(result);
7628       } else if(ifx)
7629         jmpTrueOrFalse(ifx, tlbl);
7630     } else {
7631       for(;(size--);offset++) {
7632         // normal case
7633         // result = left & right
7634         if(AOP_TYPE(right) == AOP_LIT){
7635           int t = (lit >> (offset*8)) & 0x0FFL;
7636           switch(t) { 
7637           case 0x00:
7638             pic16_emitcode("clrf","%s",
7639                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7641             break;
7642           case 0xff:
7643             pic16_emitcode("movf","%s,w",
7644                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645             pic16_emitcode("movwf","%s",
7646                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7648             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7649             break;
7650           default:
7651             pic16_emitcode("movlw","0x%x",t);
7652             pic16_emitcode("andwf","%s,w",
7653                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654             pic16_emitcode("movwf","%s",
7655                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7656               
7657             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7658             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7659             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7660           }
7661           continue;
7662         }
7663
7664         if (AOP_TYPE(left) == AOP_ACC) {
7665           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7666           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7667         } else {
7668           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7669           pic16_emitcode("andwf","%s,w",
7670                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7671           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7672           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7673         }
7674         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7675         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7676       }
7677     }
7678   }
7679
7680   release :
7681     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7682   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7683   pic16_freeAsmop(result,NULL,ic,TRUE);     
7684 }
7685
7686 /*-----------------------------------------------------------------*/
7687 /* genOr  - code for or                                            */
7688 /*-----------------------------------------------------------------*/
7689 static void genOr (iCode *ic, iCode *ifx)
7690 {
7691     operand *left, *right, *result;
7692     int size, offset=0;
7693     unsigned long lit = 0L;
7694
7695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7696
7697     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7698     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7699     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7700
7701     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7702
7703     /* if left is a literal & right is not then exchange them */
7704     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7705         AOP_NEEDSACC(left)) {
7706         operand *tmp = right ;
7707         right = left;
7708         left = tmp;
7709     }
7710
7711     /* if result = right then exchange them */
7712     if(pic16_sameRegs(AOP(result),AOP(right))){
7713         operand *tmp = right ;
7714         right = left;
7715         left = tmp;
7716     }
7717
7718     /* if right is bit then exchange them */
7719     if (AOP_TYPE(right) == AOP_CRY &&
7720         AOP_TYPE(left) != AOP_CRY){
7721         operand *tmp = right ;
7722         right = left;
7723         left = tmp;
7724     }
7725
7726     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7727
7728     if(AOP_TYPE(right) == AOP_LIT)
7729         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7730
7731     size = AOP_SIZE(result);
7732
7733     // if(bit | yy)
7734     // xx = bit | yy;
7735     if (AOP_TYPE(left) == AOP_CRY){
7736         if(AOP_TYPE(right) == AOP_LIT){
7737             // c = bit & literal;
7738             if(lit){
7739                 // lit != 0 => result = 1
7740                 if(AOP_TYPE(result) == AOP_CRY){
7741                   if(size)
7742                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7743                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7744                   //     AOP(result)->aopu.aop_dir,
7745                   //     AOP(result)->aopu.aop_dir);
7746                     else if(ifx)
7747                         continueIfTrue(ifx);
7748                     goto release;
7749                 }
7750             } else {
7751                 // lit == 0 => result = left
7752                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7753                     goto release;
7754                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7755             }
7756         } else {
7757             if (AOP_TYPE(right) == AOP_CRY){
7758               if(pic16_sameRegs(AOP(result),AOP(left))){
7759                 // c = bit | bit;
7760                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7761                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7762                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7763
7764                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7765                          AOP(result)->aopu.aop_dir,
7766                          AOP(result)->aopu.aop_dir);
7767                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7768                          AOP(right)->aopu.aop_dir,
7769                          AOP(right)->aopu.aop_dir);
7770                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7771                          AOP(result)->aopu.aop_dir,
7772                          AOP(result)->aopu.aop_dir);
7773               } else {
7774                 if( AOP_TYPE(result) == AOP_ACC) {
7775                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7776                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7779
7780                 } else {
7781
7782                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7783                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7784                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7785                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7786
7787                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7788                                  AOP(result)->aopu.aop_dir,
7789                                  AOP(result)->aopu.aop_dir);
7790                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7791                                  AOP(right)->aopu.aop_dir,
7792                                  AOP(right)->aopu.aop_dir);
7793                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7794                                  AOP(left)->aopu.aop_dir,
7795                                  AOP(left)->aopu.aop_dir);
7796                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7797                                  AOP(result)->aopu.aop_dir,
7798                                  AOP(result)->aopu.aop_dir);
7799                 }
7800               }
7801             } else {
7802                 // c = bit | val;
7803                 symbol *tlbl = newiTempLabel(NULL);
7804                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7805
7806
7807                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7808                 if( AOP_TYPE(right) == AOP_ACC) {
7809                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7810                   emitSKPNZ;
7811                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7812                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7813                 }
7814
7815
7816
7817                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7818                     pic16_emitcode(";XXX setb","c");
7819                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7820                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7821                 pic16_toBoolean(right);
7822                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7823                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7824                     jmpTrueOrFalse(ifx, tlbl);
7825                     goto release;
7826                 } else {
7827                     CLRC;
7828                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7829                 }
7830             }
7831         }
7832         // bit = c
7833         // val = c
7834         if(size)
7835             pic16_outBitC(result);
7836         // if(bit | ...)
7837         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7838             genIfxJump(ifx, "c");           
7839         goto release ;
7840     }
7841
7842     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7843     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7844     if((AOP_TYPE(right) == AOP_LIT) &&
7845        (AOP_TYPE(result) == AOP_CRY) &&
7846        (AOP_TYPE(left) != AOP_CRY)){
7847         if(lit){
7848           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849             // result = 1
7850             if(size)
7851                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7852             else 
7853                 continueIfTrue(ifx);
7854             goto release;
7855         } else {
7856           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7857             // lit = 0, result = boolean(left)
7858             if(size)
7859                 pic16_emitcode(";XXX setb","c");
7860             pic16_toBoolean(right);
7861             if(size){
7862                 symbol *tlbl = newiTempLabel(NULL);
7863                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7864                 CLRC;
7865                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7866             } else {
7867                 genIfxJump (ifx,"a");
7868                 goto release;
7869             }
7870         }
7871         pic16_outBitC(result);
7872         goto release ;
7873     }
7874
7875     /* if left is same as result */
7876     if(pic16_sameRegs(AOP(result),AOP(left))){
7877       int know_W = -1;
7878       for(;size--; offset++,lit>>=8) {
7879         if(AOP_TYPE(right) == AOP_LIT){
7880           if((lit & 0xff) == 0)
7881             /*  or'ing with 0 has no effect */
7882             continue;
7883           else {
7884             int p = pic16_my_powof2(lit & 0xff);
7885             if(p>=0) {
7886               /* only one bit is set in the literal, so use a bsf instruction */
7887               pic16_emitpcode(POC_BSF,
7888                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7889             } else {
7890               if(know_W != (lit & 0xff))
7891                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7892               know_W = lit & 0xff;
7893               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7894             }
7895                     
7896           }
7897         } else {
7898           if (AOP_TYPE(left) == AOP_ACC) {
7899             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7900 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7901           } else {                  
7902             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7903             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7904
7905 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7906 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907
7908           }
7909         }
7910       }
7911     } else {
7912         // left & result in different registers
7913         if(AOP_TYPE(result) == AOP_CRY){
7914             // result = bit
7915             // if(size), result in bit
7916             // if(!size && ifx), conditional oper: if(left | right)
7917             symbol *tlbl = newiTempLabel(NULL);
7918             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7919             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7920
7921
7922             if(size)
7923                 pic16_emitcode(";XXX setb","c");
7924             while(sizer--){
7925                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926                 pic16_emitcode(";XXX orl","a,%s",
7927                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7929                 offset++;
7930             }
7931             if(size){
7932                 CLRC;
7933                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7934                 pic16_outBitC(result);
7935             } else if(ifx)
7936                 jmpTrueOrFalse(ifx, tlbl);
7937         } else for(;(size--);offset++){
7938           // normal case
7939           // result = left & right
7940           if(AOP_TYPE(right) == AOP_LIT){
7941             int t = (lit >> (offset*8)) & 0x0FFL;
7942             switch(t) { 
7943             case 0x00:
7944               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7945               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7946
7947 //            pic16_emitcode("movf","%s,w",
7948 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7949 //            pic16_emitcode("movwf","%s",
7950 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7951               break;
7952             default:
7953               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7954               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7955               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7956
7957 //            pic16_emitcode("movlw","0x%x",t);
7958 //            pic16_emitcode("iorwf","%s,w",
7959 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7960 //            pic16_emitcode("movwf","%s",
7961 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7962               
7963             }
7964             continue;
7965           }
7966
7967           // faster than result <- left, anl result,right
7968           // and better if result is SFR
7969           if (AOP_TYPE(left) == AOP_ACC) {
7970             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7971 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7972           } else {
7973             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7974             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7975
7976 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7977 //          pic16_emitcode("iorwf","%s,w",
7978 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7979           }
7980           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7981 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7982         }
7983     }
7984
7985 release :
7986     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7987     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7988     pic16_freeAsmop(result,NULL,ic,TRUE);     
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* genXor - code for xclusive or                                   */
7993 /*-----------------------------------------------------------------*/
7994 static void genXor (iCode *ic, iCode *ifx)
7995 {
7996   operand *left, *right, *result;
7997   int size, offset=0;
7998   unsigned long lit = 0L;
7999
8000   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8001
8002   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8003   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8004   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8005
8006   /* if left is a literal & right is not ||
8007      if left needs acc & right does not */
8008   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8009       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8010     operand *tmp = right ;
8011     right = left;
8012     left = tmp;
8013   }
8014
8015   /* if result = right then exchange them */
8016   if(pic16_sameRegs(AOP(result),AOP(right))){
8017     operand *tmp = right ;
8018     right = left;
8019     left = tmp;
8020   }
8021
8022   /* if right is bit then exchange them */
8023   if (AOP_TYPE(right) == AOP_CRY &&
8024       AOP_TYPE(left) != AOP_CRY){
8025     operand *tmp = right ;
8026     right = left;
8027     left = tmp;
8028   }
8029   if(AOP_TYPE(right) == AOP_LIT)
8030     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8031
8032   size = AOP_SIZE(result);
8033
8034   // if(bit ^ yy)
8035   // xx = bit ^ yy;
8036   if (AOP_TYPE(left) == AOP_CRY){
8037     if(AOP_TYPE(right) == AOP_LIT){
8038       // c = bit & literal;
8039       if(lit>>1){
8040         // lit>>1  != 0 => result = 1
8041         if(AOP_TYPE(result) == AOP_CRY){
8042           if(size)
8043             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8044             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8045           else if(ifx)
8046             continueIfTrue(ifx);
8047           goto release;
8048         }
8049         pic16_emitcode("setb","c");
8050       } else{
8051         // lit == (0 or 1)
8052         if(lit == 0){
8053           // lit == 0, result = left
8054           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8055             goto release;
8056           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8057         } else{
8058           // lit == 1, result = not(left)
8059           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8060             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8061             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8062             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8063             goto release;
8064           } else {
8065             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8066             pic16_emitcode("cpl","c");
8067           }
8068         }
8069       }
8070
8071     } else {
8072       // right != literal
8073       symbol *tlbl = newiTempLabel(NULL);
8074       if (AOP_TYPE(right) == AOP_CRY){
8075         // c = bit ^ bit;
8076         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8077       }
8078       else{
8079         int sizer = AOP_SIZE(right);
8080         // c = bit ^ val
8081         // if val>>1 != 0, result = 1
8082         pic16_emitcode("setb","c");
8083         while(sizer){
8084           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8085           if(sizer == 1)
8086             // test the msb of the lsb
8087             pic16_emitcode("anl","a,#0xfe");
8088           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8089           sizer--;
8090         }
8091         // val = (0,1)
8092         pic16_emitcode("rrc","a");
8093       }
8094       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8095       pic16_emitcode("cpl","c");
8096       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8097     }
8098     // bit = c
8099     // val = c
8100     if(size)
8101       pic16_outBitC(result);
8102     // if(bit | ...)
8103     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8104       genIfxJump(ifx, "c");           
8105     goto release ;
8106   }
8107
8108   if(pic16_sameRegs(AOP(result),AOP(left))){
8109     /* if left is same as result */
8110     for(;size--; offset++) {
8111       if(AOP_TYPE(right) == AOP_LIT){
8112         int t  = (lit >> (offset*8)) & 0x0FFL;
8113         if(t == 0x00L)
8114           continue;
8115         else
8116           if (IS_AOP_PREG(left)) {
8117             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119             pic16_aopPut(AOP(result),"a",offset);
8120           } else {
8121             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8122             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8123             pic16_emitcode("xrl","%s,%s",
8124                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8125                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126           }
8127       } else {
8128         if (AOP_TYPE(left) == AOP_ACC)
8129           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8130         else {
8131           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8132           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8133 /*
8134           if (IS_AOP_PREG(left)) {
8135             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136             pic16_aopPut(AOP(result),"a",offset);
8137           } else
8138             pic16_emitcode("xrl","%s,a",
8139                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8140 */
8141         }
8142       }
8143     }
8144   } else {
8145     // left & result in different registers
8146     if(AOP_TYPE(result) == AOP_CRY){
8147       // result = bit
8148       // if(size), result in bit
8149       // if(!size && ifx), conditional oper: if(left ^ right)
8150       symbol *tlbl = newiTempLabel(NULL);
8151       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8152       if(size)
8153         pic16_emitcode("setb","c");
8154       while(sizer--){
8155         if((AOP_TYPE(right) == AOP_LIT) &&
8156            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8157           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158         } else {
8159           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8160           pic16_emitcode("xrl","a,%s",
8161                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8162         }
8163         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8164         offset++;
8165       }
8166       if(size){
8167         CLRC;
8168         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8169         pic16_outBitC(result);
8170       } else if(ifx)
8171         jmpTrueOrFalse(ifx, tlbl);
8172     } else for(;(size--);offset++){
8173       // normal case
8174       // result = left & right
8175       if(AOP_TYPE(right) == AOP_LIT){
8176         int t = (lit >> (offset*8)) & 0x0FFL;
8177         switch(t) { 
8178         case 0x00:
8179           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8180           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181           pic16_emitcode("movf","%s,w",
8182                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183           pic16_emitcode("movwf","%s",
8184                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185           break;
8186         case 0xff:
8187           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8188           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189           pic16_emitcode("comf","%s,w",
8190                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191           pic16_emitcode("movwf","%s",
8192                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193           break;
8194         default:
8195           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8196           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8197           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8198           pic16_emitcode("movlw","0x%x",t);
8199           pic16_emitcode("xorwf","%s,w",
8200                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8201           pic16_emitcode("movwf","%s",
8202                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8203
8204         }
8205         continue;
8206       }
8207
8208       // faster than result <- left, anl result,right
8209       // and better if result is SFR
8210       if (AOP_TYPE(left) == AOP_ACC) {
8211         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8212         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213       } else {
8214         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8215         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8216         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8218       }
8219       if ( AOP_TYPE(result) != AOP_ACC){
8220         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8221         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8222       }
8223     }
8224   }
8225
8226   release :
8227     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8228   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229   pic16_freeAsmop(result,NULL,ic,TRUE);     
8230 }
8231
8232 /*-----------------------------------------------------------------*/
8233 /* genInline - write the inline code out                           */
8234 /*-----------------------------------------------------------------*/
8235 static void genInline (iCode *ic)
8236 {
8237   char *buffer, *bp, *bp1;
8238     
8239         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8240
8241         _G.inLine += (!options.asmpeep);
8242
8243         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8244         strcpy(buffer,IC_INLINE(ic));
8245         
8246         while((bp1=strstr(bp, "\\n"))) {
8247           *bp1++ = '\n';
8248           *bp1++ = ' ';
8249           bp = bp1;
8250         }
8251         bp = bp1 = buffer;
8252
8253 #if 0
8254   /* This is an experimental code for #pragma inline
8255      and is temporarily disabled for 2.5.0 release */
8256         if(asmInlineMap)
8257         {
8258           symbol *sym;
8259           char *s;
8260           char *cbuf;
8261           int cblen;
8262
8263             cbuf = Safe_strdup(buffer);
8264             cblen = strlen(buffer)+1;
8265             memset(cbuf, 0, cblen);
8266
8267             bp = buffer;
8268             bp1 = cbuf;
8269             while(*bp) {
8270               if(*bp != '%')*bp1++ = *bp++;
8271               else {
8272                 int i;
8273
8274                   bp++;
8275                   i = *bp - '0';
8276                   if(i>elementsInSet(asmInlineMap))break;
8277                   
8278                   bp++;
8279                   s = indexSet(asmInlineMap, i);
8280                   DEBUGpc("searching symbol s = `%s'", s);
8281                   sym = findSym(SymbolTab, NULL, s);
8282
8283                   if(sym->reqv) {
8284                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8285                   } else {
8286                     strcat(bp1, sym->rname);
8287                   }
8288                   
8289                   while(*bp1)bp1++;
8290               }
8291               
8292               if(strlen(bp1) > cblen - 16) {
8293                 int i = strlen(cbuf);
8294                 cblen += 50;
8295                 cbuf = realloc(cbuf, cblen);
8296                 memset(cbuf+i, 0, 50);
8297                 bp1 = cbuf + i;
8298               }
8299             }
8300             
8301             free(buffer);
8302             buffer = Safe_strdup( cbuf );
8303             free(cbuf);
8304             
8305             bp = bp1 = buffer;
8306         }
8307 #endif  /* 0 */
8308
8309         /* emit each line as a code */
8310         while (*bp) {
8311                 if (*bp == '\n') {
8312                         *bp++ = '\0';
8313
8314                         if(*bp1)
8315                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8316                         bp1 = bp;
8317                 } else {
8318                         if (*bp == ':') {
8319                                 bp++;
8320                                 *bp = '\0';
8321                                 bp++;
8322
8323                                 /* print label, use this special format with NULL directive
8324                                  * to denote that the argument should not be indented with tab */
8325                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326                                 bp1 = bp;
8327                         } if (*bp == ';') {
8328                                 /* advance to end of line (prevent splitting of comments at ':' */
8329                                 while (*bp && *bp != '\n') {
8330                                         bp++;
8331                                 } // while
8332                         } else
8333                                 bp++;
8334                 }
8335         }
8336
8337         if ((bp1 != bp) && *bp1)
8338                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8339
8340
8341     Safe_free(buffer);
8342
8343     _G.inLine -= (!options.asmpeep);
8344 }
8345
8346 /*-----------------------------------------------------------------*/
8347 /* genRRC - rotate right with carry                                */
8348 /*-----------------------------------------------------------------*/
8349 static void genRRC (iCode *ic)
8350 {
8351   operand *left , *result ;
8352   int size, offset = 0, same;
8353
8354   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8355
8356   /* rotate right with carry */
8357   left = IC_LEFT(ic);
8358   result=IC_RESULT(ic);
8359   pic16_aopOp (left,ic,FALSE);
8360   pic16_aopOp (result,ic,TRUE);
8361
8362   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8363
8364   same = pic16_sameRegs(AOP(result),AOP(left));
8365
8366   size = AOP_SIZE(result);    
8367
8368   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8369
8370   /* get the lsb and put it into the carry */
8371   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8372
8373   offset = 0 ;
8374
8375   while(size--) {
8376
8377     if(same) {
8378       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8379     } else {
8380       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8382     }
8383
8384     offset++;
8385   }
8386
8387   pic16_freeAsmop(left,NULL,ic,TRUE);
8388   pic16_freeAsmop(result,NULL,ic,TRUE);
8389 }
8390
8391 /*-----------------------------------------------------------------*/
8392 /* genRLC - generate code for rotate left with carry               */
8393 /*-----------------------------------------------------------------*/
8394 static void genRLC (iCode *ic)
8395 {    
8396   operand *left , *result ;
8397   int size, offset = 0;
8398   int same;
8399
8400   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8401   /* rotate right with carry */
8402   left = IC_LEFT(ic);
8403   result=IC_RESULT(ic);
8404   pic16_aopOp (left,ic,FALSE);
8405   pic16_aopOp (result,ic,TRUE);
8406
8407   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8408
8409   same = pic16_sameRegs(AOP(result),AOP(left));
8410
8411   /* move it to the result */
8412   size = AOP_SIZE(result);    
8413
8414   /* get the msb and put it into the carry */
8415   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8416
8417   offset = 0 ;
8418
8419   while(size--) {
8420
8421     if(same) {
8422       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8423     } else {
8424       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8425       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8426     }
8427
8428     offset++;
8429   }
8430
8431
8432   pic16_freeAsmop(left,NULL,ic,TRUE);
8433   pic16_freeAsmop(result,NULL,ic,TRUE);
8434 }
8435
8436
8437 /* gpasm can get the highest order bit with HIGH/UPPER
8438  * so the following probably is not needed -- VR */
8439  
8440 /*-----------------------------------------------------------------*/
8441 /* genGetHbit - generates code get highest order bit               */
8442 /*-----------------------------------------------------------------*/
8443 static void genGetHbit (iCode *ic)
8444 {
8445     operand *left, *result;
8446     left = IC_LEFT(ic);
8447     result=IC_RESULT(ic);
8448     pic16_aopOp (left,ic,FALSE);
8449     pic16_aopOp (result,ic,FALSE);
8450
8451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8452     /* get the highest order byte into a */
8453     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8454     if(AOP_TYPE(result) == AOP_CRY){
8455         pic16_emitcode("rlc","a");
8456         pic16_outBitC(result);
8457     }
8458     else{
8459         pic16_emitcode("rl","a");
8460         pic16_emitcode("anl","a,#0x01");
8461         pic16_outAcc(result);
8462     }
8463
8464
8465     pic16_freeAsmop(left,NULL,ic,TRUE);
8466     pic16_freeAsmop(result,NULL,ic,TRUE);
8467 }
8468
8469 #if 0
8470 /*-----------------------------------------------------------------*/
8471 /* AccRol - rotate left accumulator by known count                 */
8472 /*-----------------------------------------------------------------*/
8473 static void AccRol (int shCount)
8474 {
8475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8476     shCount &= 0x0007;              // shCount : 0..7
8477     switch(shCount){
8478         case 0 :
8479             break;
8480         case 1 :
8481             pic16_emitcode("rl","a");
8482             break;
8483         case 2 :
8484             pic16_emitcode("rl","a");
8485             pic16_emitcode("rl","a");
8486             break;
8487         case 3 :
8488             pic16_emitcode("swap","a");
8489             pic16_emitcode("rr","a");
8490             break;
8491         case 4 :
8492             pic16_emitcode("swap","a");
8493             break;
8494         case 5 :
8495             pic16_emitcode("swap","a");
8496             pic16_emitcode("rl","a");
8497             break;
8498         case 6 :
8499             pic16_emitcode("rr","a");
8500             pic16_emitcode("rr","a");
8501             break;
8502         case 7 :
8503             pic16_emitcode("rr","a");
8504             break;
8505     }
8506 }
8507 #endif
8508
8509 /*-----------------------------------------------------------------*/
8510 /* AccLsh - left shift accumulator by known count                  */
8511 /*-----------------------------------------------------------------*/
8512 static void AccLsh (int shCount, int doMask)
8513 {
8514         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8515         switch(shCount){
8516                 case 0 :
8517                         return;
8518                         break;
8519                 case 1 :
8520                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 2 :
8523                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 3 :
8527                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 4 :
8531                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533                 case 5 :
8534                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8535                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536                         break;
8537                 case 6 :
8538                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8540                         break;
8541                 case 7 :
8542                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543                         break;
8544         }
8545         if (doMask) {
8546                 /* no masking is required in genPackBits */
8547                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8548         }
8549 }
8550
8551 /*-----------------------------------------------------------------*/
8552 /* AccRsh - right shift accumulator by known count                 */
8553 /*-----------------------------------------------------------------*/
8554 static void AccRsh (int shCount, int andmask)
8555 {
8556         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8557         switch(shCount){
8558                 case 0 :
8559                         return; break;
8560                 case 1 :
8561                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563                 case 2 :
8564                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566                         break;
8567                 case 3 :
8568                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8569                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570                         break;
8571                 case 4 :
8572                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8573                         break;
8574                 case 5 :
8575                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8576                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8577                         break;
8578                 case 6 :
8579                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8580                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8581                         break;
8582                 case 7 :
8583                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8584                         break;
8585         }
8586         
8587         if(andmask)
8588                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8589         else
8590                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8591 }
8592
8593 #if 0
8594 /*-----------------------------------------------------------------*/
8595 /* AccSRsh - signed right shift accumulator by known count                 */
8596 /*-----------------------------------------------------------------*/
8597 static void AccSRsh (int shCount)
8598 {
8599     symbol *tlbl ;
8600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8601     if(shCount != 0){
8602         if(shCount == 1){
8603             pic16_emitcode("mov","c,acc.7");
8604             pic16_emitcode("rrc","a");
8605         } else if(shCount == 2){
8606             pic16_emitcode("mov","c,acc.7");
8607             pic16_emitcode("rrc","a");
8608             pic16_emitcode("mov","c,acc.7");
8609             pic16_emitcode("rrc","a");
8610         } else {
8611             tlbl = newiTempLabel(NULL);
8612             /* rotate right accumulator */
8613             AccRol(8 - shCount);
8614             /* and kill the higher order bits */
8615             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8616             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8617             pic16_emitcode("orl","a,#0x%02x",
8618                      (unsigned char)~SRMask[shCount]);
8619             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8620         }
8621     }
8622 }
8623 #endif
8624
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR1Left2Result - shift right one byte from left to result   */
8627 /*-----------------------------------------------------------------*/
8628 static void shiftR1Left2ResultSigned (operand *left, int offl,
8629                                 operand *result, int offr,
8630                                 int shCount)
8631 {
8632   int same;
8633
8634   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8635
8636   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8637
8638   switch(shCount) {
8639   case 1:
8640     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8641     if(same) 
8642       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8643     else {
8644       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8646     }
8647
8648     break;
8649   case 2:
8650
8651     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8652     if(same) 
8653       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8654     else {
8655       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8657     }
8658     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8659     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8660
8661     break;
8662
8663   case 3:
8664     if(same)
8665       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8666     else {
8667       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669     }
8670
8671     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8672     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8673     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8674
8675     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8677
8678     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8679     break;
8680
8681   case 4:
8682     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8687     break;
8688   case 5:
8689     if(same) {
8690       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8691     } else {
8692       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8693       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8694     }
8695     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8696     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8697     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8698     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8699     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8700     break;
8701
8702   case 6:
8703     if(same) {
8704       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8705       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8707       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8708       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8710     } else {
8711       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8712       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8714       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8716     }
8717     break;
8718
8719   case 7:
8720     if(same) {
8721       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8722       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8723       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8724       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8725     } else {
8726       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8727       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8728       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8729     }
8730
8731   default:
8732     break;
8733   }
8734 }
8735
8736 /*-----------------------------------------------------------------*/
8737 /* shiftR1Left2Result - shift right one byte from left to result   */
8738 /*-----------------------------------------------------------------*/
8739 static void shiftR1Left2Result (operand *left, int offl,
8740                                 operand *result, int offr,
8741                                 int shCount, int sign)
8742 {
8743   int same;
8744
8745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746
8747   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8748
8749   /* Copy the msb into the carry if signed. */
8750   if(sign) {
8751     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8752     return;
8753   }
8754
8755
8756
8757   switch(shCount) {
8758   case 1:
8759     emitCLRC;
8760     if(same) 
8761       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762     else {
8763       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8765     }
8766     break;
8767   case 2:
8768     emitCLRC;
8769     if(same) {
8770       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8771     } else {
8772       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8773       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774     }
8775     emitCLRC;
8776     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8777
8778     break;
8779   case 3:
8780     if(same)
8781       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8782     else {
8783       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8784       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785     }
8786
8787     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8788     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8790     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791     break;
8792       
8793   case 4:
8794     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8795     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8796     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8797     break;
8798
8799   case 5:
8800     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8802     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803     //emitCLRC;
8804     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8805
8806     break;
8807   case 6:
8808
8809     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8810     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8811     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8812     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8813     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8814     break;
8815
8816   case 7:
8817
8818     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8819     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8820     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8821
8822     break;
8823
8824   default:
8825     break;
8826   }
8827 }
8828
8829 /*-----------------------------------------------------------------*/
8830 /* shiftL1Left2Result - shift left one byte from left to result    */
8831 /*-----------------------------------------------------------------*/
8832 static void shiftL1Left2Result (operand *left, int offl,
8833                                 operand *result, int offr, int shCount)
8834 {
8835   int same;
8836
8837   //    char *l;
8838   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839
8840   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8841   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8842     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8843     //    MOVA(l);
8844     /* shift left accumulator */
8845     //AccLsh(shCount, 1); // don't comment out just yet...
8846   //    pic16_aopPut(AOP(result),"a",offr);
8847
8848   switch(shCount) {
8849   case 1:
8850     /* Shift left 1 bit position */
8851     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8852     if(same) {
8853       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8854     } else {
8855       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8857     }
8858     break;
8859   case 2:
8860     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8861     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8864     break;
8865   case 3:
8866     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8867     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8868     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8871     break;
8872   case 4:
8873     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8874     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8876     break;
8877   case 5:
8878     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8879     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8880     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8881     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8882     break;
8883   case 6:
8884     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8885     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8886     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8887     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8888     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8889     break;
8890   case 7:
8891     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8893     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8894     break;
8895
8896   default:
8897     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8898   }
8899
8900 }
8901
8902 /*-----------------------------------------------------------------*/
8903 /* movLeft2Result - move byte from left to result                  */
8904 /*-----------------------------------------------------------------*/
8905 static void movLeft2Result (operand *left, int offl,
8906                             operand *result, int offr)
8907 {
8908   char *l;
8909   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8910   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8911     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8912
8913     if (*l == '@' && (IS_AOP_PREG(result))) {
8914       pic16_emitcode("mov","a,%s",l);
8915       pic16_aopPut(AOP(result),"a",offr);
8916     } else {
8917       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919     }
8920   }
8921 }
8922
8923 /*-----------------------------------------------------------------*/
8924 /* shiftL2Left2Result - shift left two bytes from left to result   */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftL2Left2Result (operand *left, int offl,
8927                                 operand *result, int offr, int shCount)
8928 {
8929   int same = pic16_sameRegs(AOP(result), AOP(left));
8930   int i;
8931
8932   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8933
8934   if (same && (offl != offr)) { // shift bytes
8935     if (offr > offl) {
8936        for(i=1;i>-1;i--) {
8937          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8938          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8939        }
8940     } else { // just treat as different later on
8941                 same = 0;
8942     }
8943   }
8944
8945   if(same) {
8946     switch(shCount) {
8947     case 0:
8948       break;
8949     case 1:
8950     case 2:
8951     case 3:
8952
8953       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8955       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8956
8957       while(--shCount) {
8958                 emitCLRC;
8959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8961       }
8962
8963       break;
8964     case 4:
8965     case 5:
8966       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8967       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8968       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8973       if(shCount >=5) {
8974                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8975                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8976       }
8977       break;
8978     case 6:
8979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8980       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8981       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8984       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8985       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8987       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8988       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8989       break;
8990     case 7:
8991       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8992       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8993       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8994       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8995       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8996     }
8997
8998   } else {
8999     switch(shCount) {
9000     case 0:
9001       break;
9002     case 1:
9003     case 2:
9004     case 3:
9005       /* note, use a mov/add for the shift since the mov has a
9006          chance of getting optimized out */
9007       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9010       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012
9013       while(--shCount) {
9014                 emitCLRC;
9015                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9016                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9017       }
9018       break;
9019
9020     case 4:
9021     case 5:
9022       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9023       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9026       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9028       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9030
9031
9032       if(shCount == 5) {
9033                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9034                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9035       }
9036       break;
9037     case 6:
9038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9041       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9042
9043       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9046       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9047       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9049       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9051       break;
9052     case 7:
9053       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9054       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9055       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9056       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9057       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9058     }
9059   }
9060
9061 }
9062 /*-----------------------------------------------------------------*/
9063 /* shiftR2Left2Result - shift right two bytes from left to result  */
9064 /*-----------------------------------------------------------------*/
9065 static void shiftR2Left2Result (operand *left, int offl,
9066                                 operand *result, int offr,
9067                                 int shCount, int sign)
9068 {
9069   int same = pic16_sameRegs(AOP(result), AOP(left));
9070   int i;
9071   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9072
9073   if (same && (offl != offr)) { // shift right bytes
9074     if (offr < offl) {
9075        for(i=0;i<2;i++) {
9076          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9077          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9078        }
9079     } else { // just treat as different later on
9080                 same = 0;
9081     }
9082   }
9083
9084   switch(shCount) {
9085   case 0:
9086     break;
9087   case 1:
9088   case 2:
9089   case 3:
9090     /* obtain sign from left operand */
9091     if(sign)
9092       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9093     else
9094       emitCLRC;
9095
9096     if(same) {
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9098       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9099     } else {
9100       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9101       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9103       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9104     }
9105
9106     while(--shCount) {
9107       if(sign)
9108         /* now get sign from already assigned result (avoid BANKSEL) */
9109         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9110       else
9111         emitCLRC;
9112       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9113       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9114     }
9115     break;
9116   case 4:
9117   case 5:
9118     if(same) {
9119
9120       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9121       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9122       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9123
9124       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9125       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9126       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9127       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9128     } else {
9129       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9130       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9131       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9132
9133       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9134       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9135       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9136       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9137       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9138     }
9139
9140     if(shCount >=5) {
9141       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9142       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9143     }
9144
9145     if(sign) {
9146       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9147       pic16_emitpcode(POC_BTFSC, 
9148                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9149       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9150     }
9151
9152     break;
9153
9154   case 6:
9155     if(same) {
9156
9157       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9158       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9159
9160       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9161       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9162       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9163       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9164       if(sign) {
9165         pic16_emitpcode(POC_BTFSC, 
9166                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9167         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9168       }
9169       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9170       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9171       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9172       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9173     } else {
9174       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9175       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9176       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9177       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9178       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9179       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9180       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9181       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9182       if(sign) {
9183         pic16_emitpcode(POC_BTFSC, 
9184                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9185         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9186       }
9187       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9188       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9189
9190         
9191     }
9192
9193     break;
9194   case 7:
9195     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9196     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9197     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9198     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9199     if(sign) {
9200       emitSKPNC;
9201       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9202     } else 
9203       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9204   }
9205 }
9206
9207
9208 /*-----------------------------------------------------------------*/
9209 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9210 /*-----------------------------------------------------------------*/
9211 static void shiftLLeftOrResult (operand *left, int offl,
9212                                 operand *result, int offr, int shCount)
9213 {
9214     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9215
9216     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9217     /* shift left accumulator */
9218     AccLsh(shCount, 1);
9219     /* or with result */
9220     /* back to result */
9221     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9226 /*-----------------------------------------------------------------*/
9227 static void shiftRLeftOrResult (operand *left, int offl,
9228                                 operand *result, int offr, int shCount)
9229 {
9230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9231     
9232     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9233     /* shift right accumulator */
9234     AccRsh(shCount, 1);
9235     /* or with result */
9236     /* back to result */
9237     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9238 }
9239
9240 /*-----------------------------------------------------------------*/
9241 /* genlshOne - left shift a one byte quantity by known count       */
9242 /*-----------------------------------------------------------------*/
9243 static void genlshOne (operand *result, operand *left, int shCount)
9244 {       
9245     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9246     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9247 }
9248
9249 /*-----------------------------------------------------------------*/
9250 /* genlshTwo - left shift two bytes by known amount != 0           */
9251 /*-----------------------------------------------------------------*/
9252 static void genlshTwo (operand *result,operand *left, int shCount)
9253 {
9254     int size;
9255     
9256     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9257     size = pic16_getDataSize(result);
9258
9259     /* if shCount >= 8 */
9260     if (shCount >= 8) {
9261         shCount -= 8 ;
9262
9263         if (size > 1){
9264             if (shCount)
9265                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9266             else 
9267                 movLeft2Result(left, LSB, result, MSB16);
9268         }
9269         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9270     }
9271
9272     /*  1 <= shCount <= 7 */
9273     else {  
9274         if(size == 1)
9275             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9276         else 
9277             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9278     }
9279 }
9280
9281 /*-----------------------------------------------------------------*/
9282 /* shiftLLong - shift left one long from left to result            */
9283 /* offr = LSB or MSB16                                             */
9284 /*-----------------------------------------------------------------*/
9285 static void shiftLLong (operand *left, operand *result, int offr )
9286 {
9287     int size = AOP_SIZE(result);
9288     int same = pic16_sameRegs(AOP(left),AOP(result));
9289         int i;
9290
9291     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9292
9293         if (same && (offr == MSB16)) { //shift one byte
9294                 for(i=size-1;i>=MSB16;i--) {
9295                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9296                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9297                 }
9298         } else {
9299                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9300         }
9301         
9302     if (size > LSB+offr ){
9303                 if (same) {
9304                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9305                 } else {
9306                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9307                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9308                 }
9309          }
9310
9311     if(size > MSB16+offr){
9312                 if (same) {
9313                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9314                 } else {
9315                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9316                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9317                 }
9318     }
9319
9320     if(size > MSB24+offr){
9321                 if (same) {
9322                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9323                 } else {
9324                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9325                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9326                 }
9327     }
9328
9329     if(size > MSB32+offr){
9330                 if (same) {
9331                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9332                 } else {
9333                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9334                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9335                 }
9336     }
9337     if(offr != LSB)
9338                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9339
9340 }
9341
9342 /*-----------------------------------------------------------------*/
9343 /* genlshFour - shift four byte by a known amount != 0             */
9344 /*-----------------------------------------------------------------*/
9345 static void genlshFour (operand *result, operand *left, int shCount)
9346 {
9347     int size;
9348
9349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9350     size = AOP_SIZE(result);
9351
9352     /* if shifting more that 3 bytes */
9353     if (shCount >= 24 ) {
9354         shCount -= 24;
9355         if (shCount)
9356             /* lowest order of left goes to the highest
9357             order of the destination */
9358             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9359         else
9360             movLeft2Result(left, LSB, result, MSB32);
9361
9362                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9363                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9364                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9365
9366         return;
9367     }
9368
9369     /* more than two bytes */
9370     else if ( shCount >= 16 ) {
9371         /* lower order two bytes goes to higher order two bytes */
9372         shCount -= 16;
9373         /* if some more remaining */
9374         if (shCount)
9375             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9376         else {
9377             movLeft2Result(left, MSB16, result, MSB32);
9378             movLeft2Result(left, LSB, result, MSB24);
9379         }
9380                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9381                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9382         return;
9383     }    
9384
9385     /* if more than 1 byte */
9386     else if ( shCount >= 8 ) {
9387         /* lower order three bytes goes to higher order  three bytes */
9388         shCount -= 8;
9389         if(size == 2){
9390             if(shCount)
9391                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9392             else
9393                 movLeft2Result(left, LSB, result, MSB16);
9394         }
9395         else{   /* size = 4 */
9396             if(shCount == 0){
9397                 movLeft2Result(left, MSB24, result, MSB32);
9398                 movLeft2Result(left, MSB16, result, MSB24);
9399                 movLeft2Result(left, LSB, result, MSB16);
9400                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9401             }
9402             else if(shCount == 1)
9403                 shiftLLong(left, result, MSB16);
9404             else{
9405                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9406                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9407                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9408                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9409             }
9410         }
9411     }
9412
9413     /* 1 <= shCount <= 7 */
9414     else if(shCount <= 3)
9415     { 
9416         shiftLLong(left, result, LSB);
9417         while(--shCount >= 1)
9418             shiftLLong(result, result, LSB);
9419     }
9420     /* 3 <= shCount <= 7, optimize */
9421     else{
9422         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9423         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9424         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9425     }
9426 }
9427
9428 /*-----------------------------------------------------------------*/
9429 /* genLeftShiftLiteral - left shifting by known count              */
9430 /*-----------------------------------------------------------------*/
9431 void pic16_genLeftShiftLiteral (operand *left,
9432                                  operand *right,
9433                                  operand *result,
9434                                  iCode *ic)
9435 {    
9436     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9437     int size;
9438
9439     FENTRY;
9440     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9441     pic16_freeAsmop(right,NULL,ic,TRUE);
9442
9443     pic16_aopOp(left,ic,FALSE);
9444     pic16_aopOp(result,ic,TRUE);
9445
9446     size = getSize(operandType(result));
9447
9448 #if VIEW_SIZE
9449     pic16_emitcode("; shift left ","result %d, left %d",size,
9450              AOP_SIZE(left));
9451 #endif
9452
9453     /* I suppose that the left size >= result size */
9454     if(shCount == 0){
9455         while(size--){
9456             movLeft2Result(left, size, result, size);
9457         }
9458     }
9459
9460     else if(shCount >= (size * 8))
9461         while(size--)
9462             pic16_aopPut(AOP(result),zero,size);
9463     else{
9464         switch (size) {
9465             case 1:
9466                 genlshOne (result,left,shCount);
9467                 break;
9468
9469             case 2:
9470             case 3:
9471                 genlshTwo (result,left,shCount);
9472                 break;
9473
9474             case 4:
9475                 genlshFour (result,left,shCount);
9476                 break;
9477         }
9478     }
9479     pic16_freeAsmop(left,NULL,ic,TRUE);
9480     pic16_freeAsmop(result,NULL,ic,TRUE);
9481 }
9482
9483 /*-----------------------------------------------------------------*
9484  * genMultiAsm - repeat assembly instruction for size of register.
9485  * if endian == 1, then the high byte (i.e base address + size of 
9486  * register) is used first else the low byte is used first;
9487  *-----------------------------------------------------------------*/
9488 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9489 {
9490
9491   int offset = 0;
9492
9493   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9494
9495   if(!reg)
9496     return;
9497
9498   if(!endian) {
9499     endian = 1;
9500   } else {
9501     endian = -1;
9502     offset = size-1;
9503   }
9504
9505   while(size--) {
9506     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9507     offset += endian;
9508   }
9509
9510 }
9511
9512 #if !(USE_GENERIC_SIGNED_SHIFT)
9513 /*-----------------------------------------------------------------*/
9514 /* genLeftShift - generates code for left shifting                 */
9515 /*-----------------------------------------------------------------*/
9516 static void genLeftShift (iCode *ic)
9517 {
9518   operand *left,*right, *result;
9519   int size, offset;
9520 //  char *l;
9521   symbol *tlbl , *tlbl1;
9522   pCodeOp *pctemp;
9523
9524   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9525
9526   right = IC_RIGHT(ic);
9527   left  = IC_LEFT(ic);
9528   result = IC_RESULT(ic);
9529
9530   pic16_aopOp(right,ic,FALSE);
9531
9532   /* if the shift count is known then do it 
9533      as efficiently as possible */
9534   if (AOP_TYPE(right) == AOP_LIT) {
9535     pic16_genLeftShiftLiteral (left,right,result,ic);
9536     return ;
9537   }
9538
9539   /* shift count is unknown then we have to form
9540    * a loop. Get the loop count in WREG : Note: we take
9541    * only the lower order byte since shifting
9542    * more than 32 bits make no sense anyway, ( the
9543    * largest size of an object can be only 32 bits ) */
9544   
9545   pic16_aopOp(left,ic,FALSE);
9546   pic16_aopOp(result,ic,FALSE);
9547
9548   /* now move the left to the result if they are not the
9549    * same, and if size > 1,
9550    * and if right is not same to result (!!!) -- VR */
9551   if (!pic16_sameRegs(AOP(left),AOP(result))
9552       && (AOP_SIZE(result) > 1)) {
9553
9554     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9555
9556     size = AOP_SIZE(result);
9557     offset=0;
9558     while (size--) {
9559
9560 #if 0
9561       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9562       if (*l == '@' && (IS_AOP_PREG(result))) {
9563
9564           pic16_emitcode("mov","a,%s",l);
9565           pic16_aopPut(AOP(result),"a",offset);
9566       } else
9567 #endif
9568       {
9569         /* we don't know if left is a literal or a register, take care -- VR */
9570         pic16_mov2f(AOP(result), AOP(left), offset);
9571       }
9572       offset++;
9573     }
9574   }
9575
9576   size = AOP_SIZE(result);
9577
9578   /* if it is only one byte then */
9579   if (size == 1) {
9580     if(optimized_for_speed) {
9581       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9582       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9583       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9584       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9585       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9586       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9587       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9588       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9589       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9590       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9591       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9592       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9593     } else {
9594
9595       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9596
9597       tlbl = newiTempLabel(NULL);
9598
9599 #if 1
9600       /* this is already done, why change it? */
9601       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9602                 pic16_mov2f(AOP(result), AOP(left), 0);
9603       }
9604 #endif
9605
9606       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9607       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9608       pic16_emitpLabel(tlbl->key);
9609       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9610       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9611       emitSKPC;
9612       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9613     }
9614     goto release ;
9615   }
9616     
9617   if (pic16_sameRegs(AOP(left),AOP(result))) {
9618
9619     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9620     
9621     tlbl = newiTempLabel(NULL);
9622     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9623     genMultiAsm(POC_RRCF, result, size,1);
9624     pic16_emitpLabel(tlbl->key);
9625     genMultiAsm(POC_RLCF, result, size,0);
9626     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9627     emitSKPC;
9628     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9629     goto release;
9630   }
9631
9632   //tlbl = newiTempLabel(NULL);
9633   //offset = 0 ;   
9634   //tlbl1 = newiTempLabel(NULL);
9635
9636   //reAdjustPreg(AOP(result));    
9637     
9638   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9639   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9640   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9641   //MOVA(l);
9642   //pic16_emitcode("add","a,acc");         
9643   //pic16_aopPut(AOP(result),"a",offset++);
9644   //while (--size) {
9645   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9646   //  MOVA(l);
9647   //  pic16_emitcode("rlc","a");         
9648   //  pic16_aopPut(AOP(result),"a",offset++);
9649   //}
9650   //reAdjustPreg(AOP(result));
9651
9652   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9653   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9654
9655
9656   tlbl = newiTempLabel(NULL);
9657   tlbl1= newiTempLabel(NULL);
9658
9659   size = AOP_SIZE(result);
9660   offset = 1;
9661
9662   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9663
9664   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9665
9666   /* offset should be 0, 1 or 3 */
9667   
9668   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9669   emitSKPNZ;
9670   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9671
9672   pic16_emitpcode(POC_MOVWF, pctemp);
9673
9674
9675   pic16_emitpLabel(tlbl->key);
9676
9677   emitCLRC;
9678   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9679   while(--size)
9680     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9681
9682   pic16_emitpcode(POC_DECFSZ,  pctemp);
9683   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9684   pic16_emitpLabel(tlbl1->key);
9685
9686   pic16_popReleaseTempReg(pctemp,1);
9687
9688
9689  release:
9690   pic16_freeAsmop (right,NULL,ic,TRUE);
9691   pic16_freeAsmop(left,NULL,ic,TRUE);
9692   pic16_freeAsmop(result,NULL,ic,TRUE);
9693 }
9694 #endif
9695
9696
9697 #if 0
9698 #error old code (left here for reference)
9699 /*-----------------------------------------------------------------*/
9700 /* genLeftShift - generates code for left shifting                 */
9701 /*-----------------------------------------------------------------*/
9702 static void genLeftShift (iCode *ic)
9703 {
9704   operand *left,*right, *result;
9705   int size, offset;
9706   char *l;
9707   symbol *tlbl , *tlbl1;
9708   pCodeOp *pctemp;
9709
9710   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9711
9712   right = IC_RIGHT(ic);
9713   left  = IC_LEFT(ic);
9714   result = IC_RESULT(ic);
9715
9716   pic16_aopOp(right,ic,FALSE);
9717
9718   /* if the shift count is known then do it 
9719      as efficiently as possible */
9720   if (AOP_TYPE(right) == AOP_LIT) {
9721     pic16_genLeftShiftLiteral (left,right,result,ic);
9722     return ;
9723   }
9724
9725   /* shift count is unknown then we have to form 
9726      a loop get the loop count in B : Note: we take
9727      only the lower order byte since shifting
9728      more that 32 bits make no sense anyway, ( the
9729      largest size of an object can be only 32 bits ) */  
9730
9731     
9732   pic16_aopOp(left,ic,FALSE);
9733   pic16_aopOp(result,ic,FALSE);
9734
9735   /* now move the left to the result if they are not the
9736      same */
9737   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9738       AOP_SIZE(result) > 1) {
9739
9740     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9741
9742     size = AOP_SIZE(result);
9743     offset=0;
9744     while (size--) {
9745       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9746       if (*l == '@' && (IS_AOP_PREG(result))) {
9747
9748         pic16_emitcode("mov","a,%s",l);
9749         pic16_aopPut(AOP(result),"a",offset);
9750       } else {
9751
9752         /* we don't know if left is a literal or a register, take care -- VR */
9753         pic16_mov2f(AOP(result), AOP(left), offset);
9754       }
9755       offset++;
9756     }
9757   }
9758
9759   size = AOP_SIZE(result);
9760
9761   /* if it is only one byte then */
9762   if (size == 1) {
9763     if(optimized_for_speed) {
9764       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9765       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9766       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9767       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9768       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9769       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9770       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9771       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9772       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9773       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9774       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9775       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9776     } else {
9777
9778       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9779
9780       tlbl = newiTempLabel(NULL);
9781       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9782                 pic16_mov2f(AOP(result), AOP(left), 0);
9783                 
9784 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9785 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9786       }
9787
9788       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9789       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9790       pic16_emitpLabel(tlbl->key);
9791       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9792       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9793       emitSKPC;
9794       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9795     }
9796     goto release ;
9797   }
9798     
9799   if (pic16_sameRegs(AOP(left),AOP(result))) {
9800
9801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9802     
9803     tlbl = newiTempLabel(NULL);
9804     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9805     genMultiAsm(POC_RRCF, result, size,1);
9806     pic16_emitpLabel(tlbl->key);
9807     genMultiAsm(POC_RLCF, result, size,0);
9808     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9809     emitSKPC;
9810     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9811     goto release;
9812   }
9813
9814   //tlbl = newiTempLabel(NULL);
9815   //offset = 0 ;   
9816   //tlbl1 = newiTempLabel(NULL);
9817
9818   //reAdjustPreg(AOP(result));    
9819     
9820   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9821   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9822   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9823   //MOVA(l);
9824   //pic16_emitcode("add","a,acc");         
9825   //pic16_aopPut(AOP(result),"a",offset++);
9826   //while (--size) {
9827   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9828   //  MOVA(l);
9829   //  pic16_emitcode("rlc","a");         
9830   //  pic16_aopPut(AOP(result),"a",offset++);
9831   //}
9832   //reAdjustPreg(AOP(result));
9833
9834   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9835   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9836
9837
9838   tlbl = newiTempLabel(NULL);
9839   tlbl1= newiTempLabel(NULL);
9840
9841   size = AOP_SIZE(result);
9842   offset = 1;
9843
9844   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9845
9846   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9847
9848   /* offset should be 0, 1 or 3 */
9849   
9850   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9851   emitSKPNZ;
9852   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9853
9854   pic16_emitpcode(POC_MOVWF, pctemp);
9855
9856
9857   pic16_emitpLabel(tlbl->key);
9858
9859   emitCLRC;
9860   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9861   while(--size)
9862     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9863
9864   pic16_emitpcode(POC_DECFSZ,  pctemp);
9865   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9866   pic16_emitpLabel(tlbl1->key);
9867
9868   pic16_popReleaseTempReg(pctemp,1);
9869
9870
9871  release:
9872   pic16_freeAsmop (right,NULL,ic,TRUE);
9873   pic16_freeAsmop(left,NULL,ic,TRUE);
9874   pic16_freeAsmop(result,NULL,ic,TRUE);
9875 }
9876 #endif
9877
9878 /*-----------------------------------------------------------------*/
9879 /* genrshOne - right shift a one byte quantity by known count      */
9880 /*-----------------------------------------------------------------*/
9881 static void genrshOne (operand *result, operand *left,
9882                        int shCount, int sign)
9883 {
9884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9885     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9886 }
9887
9888 /*-----------------------------------------------------------------*/
9889 /* genrshTwo - right shift two bytes by known amount != 0          */
9890 /*-----------------------------------------------------------------*/
9891 static void genrshTwo (operand *result,operand *left,
9892                        int shCount, int sign)
9893 {
9894   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9895   /* if shCount >= 8 */
9896   if (shCount >= 8) {
9897     shCount -= 8 ;
9898     if (shCount)
9899       shiftR1Left2Result(left, MSB16, result, LSB,
9900                          shCount, sign);
9901     else
9902       movLeft2Result(left, MSB16, result, LSB);
9903
9904     pic16_addSign (result, 1, sign);
9905   }
9906
9907   /*  1 <= shCount <= 7 */
9908   else
9909     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9910 }
9911
9912 /*-----------------------------------------------------------------*/
9913 /* shiftRLong - shift right one long from left to result           */
9914 /* offl = LSB or MSB16                                             */
9915 /*-----------------------------------------------------------------*/
9916 static void shiftRLong (operand *left, int offl,
9917                         operand *result, int sign)
9918 {
9919     int size = AOP_SIZE(result);
9920     int same = pic16_sameRegs(AOP(left),AOP(result));
9921     int i;
9922     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9923
9924         if (same && (offl == MSB16)) { //shift one byte right
9925                 for(i=MSB16;i<size;i++) {
9926                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9927                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9928                 }
9929         }
9930
9931     if(sign)
9932                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9933         else
9934                 emitCLRC;
9935
9936         if (same) {
9937                 if (offl == LSB)
9938                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9939         } else {
9940         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9941         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9942         }
9943
9944     if(offl == MSB16) {
9945         /* add sign of "a" */
9946         pic16_addSign(result, MSB32, sign);
9947         }
9948
9949         if (same) {
9950         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9951         } else {
9952         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9953         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9954         }
9955         
9956         if (same) {
9957         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9958         } else {
9959         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9960         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9961         }
9962
9963         if (same) {
9964         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9965         } else {
9966         if(offl == LSB){
9967                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9968                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9969         }
9970         }
9971 }
9972
9973 /*-----------------------------------------------------------------*/
9974 /* genrshFour - shift four byte by a known amount != 0             */
9975 /*-----------------------------------------------------------------*/
9976 static void genrshFour (operand *result, operand *left,
9977                         int shCount, int sign)
9978 {
9979   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9980   /* if shifting more that 3 bytes */
9981   if(shCount >= 24 ) {
9982     shCount -= 24;
9983     if(shCount)
9984       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9985     else
9986       movLeft2Result(left, MSB32, result, LSB);
9987
9988     pic16_addSign(result, MSB16, sign);
9989   }
9990   else if(shCount >= 16){
9991     shCount -= 16;
9992     if(shCount)
9993       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9994     else{
9995       movLeft2Result(left, MSB24, result, LSB);
9996       movLeft2Result(left, MSB32, result, MSB16);
9997     }
9998     pic16_addSign(result, MSB24, sign);
9999   }
10000   else if(shCount >= 8){
10001     shCount -= 8;
10002     if(shCount == 1)
10003       shiftRLong(left, MSB16, result, sign);
10004     else if(shCount == 0){
10005       movLeft2Result(left, MSB16, result, LSB);
10006       movLeft2Result(left, MSB24, result, MSB16);
10007       movLeft2Result(left, MSB32, result, MSB24);
10008       pic16_addSign(result, MSB32, sign);
10009     }
10010     else{ //shcount >= 2
10011       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10012       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10013       /* the last shift is signed */
10014       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10015       pic16_addSign(result, MSB32, sign);
10016     }
10017   }
10018   else{   /* 1 <= shCount <= 7 */
10019     if(shCount <= 2){
10020       shiftRLong(left, LSB, result, sign);
10021       if(shCount == 2)
10022         shiftRLong(result, LSB, result, sign);
10023     }
10024     else{
10025       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10026       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10027       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10028     }
10029   }
10030 }
10031
10032 /*-----------------------------------------------------------------*/
10033 /* genRightShiftLiteral - right shifting by known count            */
10034 /*-----------------------------------------------------------------*/
10035 static void genRightShiftLiteral (operand *left,
10036                                   operand *right,
10037                                   operand *result,
10038                                   iCode *ic,
10039                                   int sign)
10040 {    
10041   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10042   int lsize,res_size;
10043
10044   pic16_freeAsmop(right,NULL,ic,TRUE);
10045
10046   pic16_aopOp(left,ic,FALSE);
10047   pic16_aopOp(result,ic,TRUE);
10048
10049   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10050
10051 #if VIEW_SIZE
10052   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10053                  AOP_SIZE(left));
10054 #endif
10055
10056   lsize = pic16_getDataSize(left);
10057   res_size = pic16_getDataSize(result);
10058   /* test the LEFT size !!! */
10059
10060   /* I suppose that the left size >= result size */
10061   if(shCount == 0){
10062     assert (res_size <= lsize);
10063     while (res_size--) {
10064       pic16_mov2f (AOP(result), AOP(left), res_size);
10065     } // for
10066   }
10067
10068   else if(shCount >= (lsize * 8)){
10069
10070     if(res_size == 1) {
10071       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10072       if(sign) {
10073         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10074         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10075       }
10076     } else {
10077
10078       if(sign) {
10079         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10080         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10081         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10082         while(res_size--)
10083           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10084
10085       } else {
10086
10087         while(res_size--)
10088           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10089       }
10090     }
10091   } else {
10092
10093     switch (res_size) {
10094     case 1:
10095       genrshOne (result,left,shCount,sign);
10096       break;
10097
10098     case 2:
10099       genrshTwo (result,left,shCount,sign);
10100       break;
10101
10102     case 4:
10103       genrshFour (result,left,shCount,sign);
10104       break;
10105     default :
10106       break;
10107     }
10108
10109   }
10110
10111   pic16_freeAsmop(left,NULL,ic,TRUE);
10112   pic16_freeAsmop(result,NULL,ic,TRUE);
10113 }
10114
10115 #if !(USE_GENERIC_SIGNED_SHIFT)
10116 /*-----------------------------------------------------------------*/
10117 /* genSignedRightShift - right shift of signed number              */
10118 /*-----------------------------------------------------------------*/
10119 static void genSignedRightShift (iCode *ic)
10120 {
10121   operand *right, *left, *result;
10122   int size, offset;
10123   //  char *l;
10124   symbol *tlbl, *tlbl1 ;
10125   pCodeOp *pctemp;
10126
10127   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10128
10129   /* we do it the hard way put the shift count in b
10130      and loop thru preserving the sign */
10131   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10132
10133   right = IC_RIGHT(ic);
10134   left  = IC_LEFT(ic);
10135   result = IC_RESULT(ic);
10136
10137   pic16_aopOp(right,ic,FALSE);  
10138   pic16_aopOp(left,ic,FALSE);
10139   pic16_aopOp(result,ic,FALSE);
10140
10141
10142   if ( AOP_TYPE(right) == AOP_LIT) {
10143     genRightShiftLiteral (left,right,result,ic,1);
10144     return ;
10145   }
10146   /* shift count is unknown then we have to form 
10147      a loop get the loop count in B : Note: we take
10148      only the lower order byte since shifting
10149      more that 32 bits make no sense anyway, ( the
10150      largest size of an object can be only 32 bits ) */  
10151
10152   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10153   //pic16_emitcode("inc","b");
10154   //pic16_freeAsmop (right,NULL,ic,TRUE);
10155   //pic16_aopOp(left,ic,FALSE);
10156   //pic16_aopOp(result,ic,FALSE);
10157
10158   /* now move the left to the result if they are not the
10159      same */
10160   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10161       AOP_SIZE(result) > 1) {
10162
10163     size = AOP_SIZE(result);
10164     offset=0;
10165     while (size--) { 
10166       /*
10167         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10168         if (*l == '@' && IS_AOP_PREG(result)) {
10169
10170         pic16_emitcode("mov","a,%s",l);
10171         pic16_aopPut(AOP(result),"a",offset);
10172         } else
10173         pic16_aopPut(AOP(result),l,offset);
10174       */
10175       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10176       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10177
10178       offset++;
10179     }
10180   }
10181
10182   /* mov the highest order bit to OVR */    
10183   tlbl = newiTempLabel(NULL);
10184   tlbl1= newiTempLabel(NULL);
10185
10186   size = AOP_SIZE(result);
10187   offset = size - 1;
10188
10189   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10190
10191   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10192
10193   /* offset should be 0, 1 or 3 */
10194   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10195   emitSKPNZ;
10196   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10197
10198   pic16_emitpcode(POC_MOVWF, pctemp);
10199
10200
10201   pic16_emitpLabel(tlbl->key);
10202
10203   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10204   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10205
10206   while(--size) {
10207     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10208   }
10209
10210   pic16_emitpcode(POC_DECFSZ,  pctemp);
10211   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10212   pic16_emitpLabel(tlbl1->key);
10213
10214   pic16_popReleaseTempReg(pctemp,1);
10215 #if 0
10216   size = AOP_SIZE(result);
10217   offset = size - 1;
10218   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10219   pic16_emitcode("rlc","a");
10220   pic16_emitcode("mov","ov,c");
10221   /* if it is only one byte then */
10222   if (size == 1) {
10223     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10224     MOVA(l);
10225     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10227     pic16_emitcode("mov","c,ov");
10228     pic16_emitcode("rrc","a");
10229     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10230     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10231     pic16_aopPut(AOP(result),"a",0);
10232     goto release ;
10233   }
10234
10235   reAdjustPreg(AOP(result));
10236   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10237   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10238   pic16_emitcode("mov","c,ov");
10239   while (size--) {
10240     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10241     MOVA(l);
10242     pic16_emitcode("rrc","a");         
10243     pic16_aopPut(AOP(result),"a",offset--);
10244   }
10245   reAdjustPreg(AOP(result));
10246   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10247   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10248
10249  release:
10250 #endif
10251
10252   pic16_freeAsmop(left,NULL,ic,TRUE);
10253   pic16_freeAsmop(result,NULL,ic,TRUE);
10254   pic16_freeAsmop(right,NULL,ic,TRUE);
10255 }
10256 #endif
10257
10258 #if !(USE_GENERIC_SIGNED_SHIFT)
10259 #warning This implementation of genRightShift() is incomplete!
10260 /*-----------------------------------------------------------------*/
10261 /* genRightShift - generate code for right shifting                */
10262 /*-----------------------------------------------------------------*/
10263 static void genRightShift (iCode *ic)
10264 {
10265     operand *right, *left, *result;
10266     sym_link *letype ;
10267     int size, offset;
10268     char *l;
10269     symbol *tlbl, *tlbl1 ;
10270
10271     /* if signed then we do it the hard way preserve the
10272     sign bit moving it inwards */
10273     letype = getSpec(operandType(IC_LEFT(ic)));
10274     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10275
10276     if (!SPEC_USIGN(letype)) {
10277         genSignedRightShift (ic);
10278         return ;
10279     }
10280
10281     /* signed & unsigned types are treated the same : i.e. the
10282     signed is NOT propagated inwards : quoting from the
10283     ANSI - standard : "for E1 >> E2, is equivalent to division
10284     by 2**E2 if unsigned or if it has a non-negative value,
10285     otherwise the result is implementation defined ", MY definition
10286     is that the sign does not get propagated */
10287
10288     right = IC_RIGHT(ic);
10289     left  = IC_LEFT(ic);
10290     result = IC_RESULT(ic);
10291
10292     pic16_aopOp(right,ic,FALSE);
10293
10294     /* if the shift count is known then do it 
10295     as efficiently as possible */
10296     if (AOP_TYPE(right) == AOP_LIT) {
10297         genRightShiftLiteral (left,right,result,ic, 0);
10298         return ;
10299     }
10300
10301     /* shift count is unknown then we have to form 
10302     a loop get the loop count in B : Note: we take
10303     only the lower order byte since shifting
10304     more that 32 bits make no sense anyway, ( the
10305     largest size of an object can be only 32 bits ) */  
10306
10307     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10308     pic16_emitcode("inc","b");
10309     pic16_aopOp(left,ic,FALSE);
10310     pic16_aopOp(result,ic,FALSE);
10311
10312     /* now move the left to the result if they are not the
10313     same */
10314     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10315         AOP_SIZE(result) > 1) {
10316
10317         size = AOP_SIZE(result);
10318         offset=0;
10319         while (size--) {
10320             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10321             if (*l == '@' && IS_AOP_PREG(result)) {
10322
10323                 pic16_emitcode("mov","a,%s",l);
10324                 pic16_aopPut(AOP(result),"a",offset);
10325             } else
10326                 pic16_aopPut(AOP(result),l,offset);
10327             offset++;
10328         }
10329     }
10330
10331     tlbl = newiTempLabel(NULL);
10332     tlbl1= newiTempLabel(NULL);
10333     size = AOP_SIZE(result);
10334     offset = size - 1;
10335
10336     /* if it is only one byte then */
10337     if (size == 1) {
10338
10339       tlbl = newiTempLabel(NULL);
10340       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10341         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10342         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10343       }
10344
10345       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10346       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10347       pic16_emitpLabel(tlbl->key);
10348       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10349       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10350       emitSKPC;
10351       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10352
10353       goto release ;
10354     }
10355
10356     reAdjustPreg(AOP(result));
10357     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10358     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10359     CLRC;
10360     while (size--) {
10361         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10362         MOVA(l);
10363         pic16_emitcode("rrc","a");         
10364         pic16_aopPut(AOP(result),"a",offset--);
10365     }
10366     reAdjustPreg(AOP(result));
10367
10368     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10369     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10370
10371 release:
10372     pic16_freeAsmop(left,NULL,ic,TRUE);
10373     pic16_freeAsmop (right,NULL,ic,TRUE);
10374     pic16_freeAsmop(result,NULL,ic,TRUE);
10375 }
10376 #endif
10377
10378 #if (USE_GENERIC_SIGNED_SHIFT)
10379 /*-----------------------------------------------------------------*/
10380 /* genGenericShift - generates code for left or right shifting     */
10381 /*-----------------------------------------------------------------*/
10382 static void genGenericShift (iCode *ic, int isShiftLeft) {
10383   operand *left,*right, *result;
10384   int offset;
10385   int sign, signedCount;
10386   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10387   PIC_OPCODE pos_shift, neg_shift;
10388
10389   FENTRY;
10390
10391   right = IC_RIGHT(ic);
10392   left  = IC_LEFT(ic);
10393   result = IC_RESULT(ic);
10394
10395   pic16_aopOp(right,ic,FALSE);
10396   pic16_aopOp(left,ic,FALSE);
10397   pic16_aopOp(result,ic,TRUE);
10398
10399   sign = !SPEC_USIGN(operandType (left));
10400   signedCount = !SPEC_USIGN(operandType (right));
10401
10402   /* if the shift count is known then do it 
10403      as efficiently as possible */
10404   if (AOP_TYPE(right) == AOP_LIT) {
10405     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10406     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10407     // we should modify right->aopu.aop_lit here!
10408     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10409     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10410     if (isShiftLeft)
10411       pic16_genLeftShiftLiteral (left,right,result,ic);
10412     else
10413       genRightShiftLiteral (left,right,result,ic, sign);
10414
10415     goto release;
10416   } // if (right is literal)
10417
10418   /* shift count is unknown then we have to form a loop.
10419    * Note: we take only the lower order byte since shifting
10420    * more than 32 bits make no sense anyway, ( the
10421    * largest size of an object can be only 32 bits )
10422    * Note: we perform arithmetic shifts if the left operand is
10423    * signed and we do an (effective) right shift, i. e. we
10424    * shift in the sign bit from the left. */
10425    
10426   label_complete = newiTempLabel ( NULL );
10427   label_loop_pos = newiTempLabel ( NULL );
10428   label_loop_neg = NULL;
10429   label_negative = NULL;
10430   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10431   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10432
10433   if (signedCount) {
10434     // additional labels needed
10435     label_loop_neg = newiTempLabel ( NULL );
10436     label_negative = newiTempLabel ( NULL );
10437   } // if
10438
10439   // copy source to result -- this will effectively truncate the left operand to the size of result!
10440   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10441   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10442   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10443     pic16_mov2f (AOP(result),AOP(left), offset);
10444   } // for
10445
10446   // if result is longer than left, fill with zeros (or sign)
10447   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10448     if (sign && AOP_SIZE(left) > 0) {
10449       // shift signed operand -- fill with sign
10450       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10451       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10452       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10453       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10454         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10455       } // for
10456     } else {
10457       // shift unsigned operand -- fill result with zeros
10458       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10459         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10460       } // for
10461     }
10462   } // if (size mismatch)
10463
10464   pic16_mov2w (AOP(right), 0);
10465   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10466   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10467   
10468 #if 0
10469   // perform a shift by one (shift count is positive)
10470   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10471   // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3]          ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10472   pic16_emitpLabel (label_loop_pos->key);
10473   emitCLRC;
10474   if (sign && (pos_shift == POC_RRCF)) {
10475     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10476     emitSETC;
10477   } // if
10478   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10479   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10480   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10481 #else
10482   // perform a shift by one (shift count is positive)
10483   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10484   // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6]        ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10485   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10486   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10487   emitCLRC;
10488   pic16_emitpLabel (label_loop_pos->key);
10489   if (sign && (pos_shift == POC_RRCF)) {
10490     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10491     emitSETC;
10492   } // if
10493   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10494   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10497 #endif
10498
10499   if (signedCount) {
10500     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10501
10502     pic16_emitpLabel (label_negative->key);
10503     // perform a shift by -1 (shift count is negative)
10504     // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4                   ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10505     emitCLRC;
10506     pic16_emitpLabel (label_loop_neg->key);
10507     if (sign && (neg_shift == POC_RRCF)) {
10508       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10509       emitSETC;
10510     } // if
10511     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10512     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10513     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10514     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10515   } // if (signedCount)
10516
10517   pic16_emitpLabel (label_complete->key);
10518
10519 release:
10520   pic16_freeAsmop (right,NULL,ic,TRUE);
10521   pic16_freeAsmop(left,NULL,ic,TRUE);
10522   pic16_freeAsmop(result,NULL,ic,TRUE);
10523 }
10524
10525 static void genLeftShift (iCode *ic) {
10526   genGenericShift (ic, 1);
10527 }
10528
10529 static void genRightShift (iCode *ic) {
10530   genGenericShift (ic, 0);
10531 }
10532 #endif
10533
10534
10535 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10536 void pic16_loadFSR0(operand *op, int lit)
10537 {
10538   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10539     if (AOP_TYPE(op) == AOP_LIT) {
10540       /* handle 12 bit integers correctly */
10541       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10542       if ((val & 0x0fff) != val) {
10543         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10544                 val, (val & 0x0fff) );
10545         val &= 0x0fff;
10546       }
10547       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10548     } else {
10549       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10550     }
10551   } else {
10552     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10553     // set up FSR0 with address of result
10554     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10555     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10556   }
10557 }
10558
10559 /*----------------------------------------------------------------*/
10560 /* pic16_derefPtr - move one byte from the location ptr points to */
10561 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10562 /*                  to the location ptr points to (doWrite != 0)   */
10563 /*----------------------------------------------------------------*/
10564 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10565 {
10566   if (!IS_PTR(operandType(ptr)))
10567   {
10568     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10569     else pic16_mov2w (AOP(ptr), 0);
10570     return;
10571   }
10572
10573   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10574   /* We might determine pointer type right here: */
10575   p_type = DCL_TYPE(operandType(ptr));
10576
10577   switch (p_type) {
10578     case FPOINTER:
10579     case POINTER:
10580       if (!fsr0_setup || !*fsr0_setup)
10581       {
10582         pic16_loadFSR0( ptr, 0 );
10583         if (fsr0_setup) *fsr0_setup = 1;
10584       }
10585       if (doWrite)
10586         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10587       else
10588         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10589       break;
10590
10591     case GPOINTER:
10592       if (AOP(ptr)->aopu.aop_reg[2]) {
10593         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10594         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10595         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10596         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10597         pic16_mov2w(AOP(ptr), 2);
10598         pic16_callGenericPointerRW(doWrite, 1);
10599       } else {
10600         // data pointer (just 2 byte given)
10601         if (!fsr0_setup || !*fsr0_setup)
10602         {
10603           pic16_loadFSR0( ptr, 0 );
10604           if (fsr0_setup) *fsr0_setup = 1;
10605         }
10606         if (doWrite)
10607           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10608         else
10609           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10610       }
10611       break;
10612
10613     default:
10614       assert (0 && "invalid pointer type specified");
10615       break;
10616   }
10617 }
10618
10619 /*-----------------------------------------------------------------*/
10620 /* genUnpackBits - generates code for unpacking bits               */
10621 /*-----------------------------------------------------------------*/
10622 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10623 {    
10624   int shCnt ;
10625   sym_link *etype, *letype;
10626   int blen=0, bstr=0;
10627   int lbstr;
10628   int same;
10629   pCodeOp *op;
10630
10631   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10632   etype = getSpec(operandType(result));
10633   letype = getSpec(operandType(left));
10634
10635   //    if(IS_BITFIELD(etype)) {
10636   blen = SPEC_BLEN(etype);
10637   bstr = SPEC_BSTR(etype);
10638   //    }
10639
10640   lbstr = SPEC_BSTR( letype );
10641
10642   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10643       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10644
10645 #if 1
10646   if((blen == 1) && (bstr < 8)
10647       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10648     /* it is a single bit, so use the appropriate bit instructions */
10649     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10650
10651     same = pic16_sameRegs(AOP(left),AOP(result));
10652     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10653     pic16_emitpcode(POC_CLRF, op);
10654
10655     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10656       /* workaround to reduce the extra lfsr instruction */
10657       pic16_emitpcode(POC_BTFSC,
10658           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10659     } else {
10660       assert (PIC_IS_DATA_PTR (operandType(left)));
10661       pic16_loadFSR0 (left, 0);
10662       pic16_emitpcode(POC_BTFSC,
10663           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10664     }
10665
10666     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10667       /* unsigned bitfields result in either 0 or 1 */
10668       pic16_emitpcode(POC_INCF, op);
10669     } else {
10670       /* signed bitfields result in either 0 or -1 */
10671       pic16_emitpcode(POC_DECF, op);
10672     }
10673     if (same) {
10674       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10675     }
10676
10677     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10678     return;
10679   }
10680
10681 #endif
10682
10683   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10684     // access symbol directly
10685     pic16_mov2w (AOP(left), 0);
10686   } else {
10687     pic16_derefPtr (left, ptype, 0, NULL);
10688   }
10689
10690   /* if we have bitdisplacement then it fits   */
10691   /* into this byte completely or if length is */
10692   /* less than a byte                          */
10693   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10694
10695     /* shift right acc */
10696     AccRsh(shCnt, 0);
10697
10698     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10699           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10700
10701     /* VR -- normally I would use the following, but since we use the hack,
10702      * to avoid the masking from AccRsh, why not mask it right now? */
10703
10704     /*
10705        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10706      */
10707
10708     /* extend signed bitfields to 8 bits */
10709     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10710     {
10711       assert (blen + bstr > 0);
10712       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10713       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10714     }
10715
10716     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10717
10718     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10719     return ;
10720   }
10721
10722   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10723   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10724   exit(EXIT_FAILURE);
10725
10726   return ;
10727 }
10728
10729
10730 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10731 {
10732   int size, offset = 0, leoffset=0 ;
10733
10734         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10735         pic16_aopOp(result, ic, TRUE);
10736
10737         FENTRY;
10738
10739         size = AOP_SIZE(result);
10740 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10741
10742
10743 #if 1
10744         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10745                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10746                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10747                 goto release;
10748         }
10749 #endif
10750
10751         if(AOP(left)->aopu.pcop->type == PO_DIR)
10752                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10753
10754         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10755
10756         while (size--) {
10757                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10758                 
10759 //              pic16_DumpOp("(result)",result);
10760                 if(is_LitAOp(AOP(result))) {
10761                         pic16_mov2w(AOP(left), offset); // patch 8
10762                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10763                 } else {
10764                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10765                                 pic16_popGet(AOP(left), offset), //patch 8
10766                                 pic16_popGet(AOP(result), offset)));
10767                 }
10768
10769                 offset++;
10770                 leoffset++;
10771         }
10772
10773 release:
10774     pic16_freeAsmop(result,NULL,ic,TRUE);
10775 }
10776
10777
10778
10779 /*-----------------------------------------------------------------*/
10780 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10781 /*-----------------------------------------------------------------*/
10782 static void genNearPointerGet (operand *left, 
10783                                operand *result, 
10784                                iCode *ic)
10785 {
10786 //  asmop *aop = NULL;
10787   //regs *preg = NULL ;
10788   sym_link *rtype, *retype;
10789   sym_link *ltype, *letype;
10790
10791     FENTRY;
10792     
10793     rtype = operandType(result);
10794     retype= getSpec(rtype);
10795     ltype = operandType(left);
10796     letype= getSpec(ltype);
10797     
10798     pic16_aopOp(left,ic,FALSE);
10799
10800 //    pic16_DumpOp("(left)",left);
10801 //    pic16_DumpOp("(result)",result);
10802
10803     /* if left is rematerialisable and
10804      * result is not bit variable type and
10805      * the left is pointer to data space i.e
10806      * lower 128 bytes of space */
10807     
10808     if (AOP_TYPE(left) == AOP_PCODE
10809       && !IS_BITFIELD(retype)
10810       && DCL_TYPE(ltype) == POINTER) {
10811
10812         genDataPointerGet (left,result,ic);
10813         pic16_freeAsmop(left, NULL, ic, TRUE);
10814         return ;
10815     }
10816     
10817     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10818     pic16_aopOp (result,ic,TRUE);
10819     
10820     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10821
10822 #if 1
10823     if(IS_BITFIELD( retype )
10824       && (SPEC_BLEN(operandType(result))==1)
10825     ) {
10826       iCode *nextic;
10827       pCodeOp *jop;
10828       int bitstrt, bytestrt;
10829
10830         /* if this is bitfield of size 1, see if we are checking the value
10831          * of a single bit in an if-statement,
10832          * if yes, then don't generate usual code, but execute the
10833          * genIfx directly -- VR */
10834
10835         nextic = ic->next;
10836
10837         /* CHECK: if next iCode is IFX
10838          * and current result operand is nextic's conditional operand
10839          * and current result operand live ranges ends at nextic's key number
10840          */
10841         if((nextic->op == IFX)
10842           && (result == IC_COND(nextic))
10843           && (OP_LIVETO(result) == nextic->seq)
10844           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10845           ) {
10846             /* everything is ok then */
10847             /* find a way to optimize the genIfx iCode */
10848
10849             bytestrt = SPEC_BSTR(operandType(result))/8;
10850             bitstrt = SPEC_BSTR(operandType(result))%8;
10851             
10852             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10853
10854             genIfxpCOpJump(nextic, jop);
10855             
10856             pic16_freeAsmop(left, NULL, ic, TRUE);
10857             pic16_freeAsmop(result, NULL, ic, TRUE);
10858             return;
10859         }
10860     }
10861 #endif
10862
10863     /* if bitfield then unpack the bits */
10864     if (IS_BITFIELD(letype)) 
10865       genUnpackBits (result, left, NULL, POINTER);
10866     else {
10867       /* we have can just get the values */
10868       int size = AOP_SIZE(result);
10869       int offset = 0;   
10870         
10871       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10872
10873       pic16_loadFSR0( left, 0 );
10874
10875       while(size--) {
10876         if(size) {
10877           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10878                 pic16_popGet(AOP(result), offset++)));
10879         } else {
10880           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10881                 pic16_popGet(AOP(result), offset++)));
10882         }
10883       }
10884     }
10885
10886 #if 0
10887     /* now some housekeeping stuff */
10888     if (aop) {
10889       /* we had to allocate for this iCode */
10890       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10891       pic16_freeAsmop(NULL,aop,ic,TRUE);
10892     } else { 
10893       /* we did not allocate which means left
10894        * already in a pointer register, then
10895        * if size > 0 && this could be used again
10896        * we have to point it back to where it 
10897        * belongs */
10898       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10899       if (AOP_SIZE(result) > 1
10900         && !OP_SYMBOL(left)->remat
10901         && ( OP_SYMBOL(left)->liveTo > ic->seq
10902             || ic->depth )) {
10903 //        int size = AOP_SIZE(result) - 1;
10904 //        while (size--)
10905 //          pic16_emitcode("dec","%s",rname);
10906         }
10907     }
10908 #endif
10909
10910     /* done */
10911     pic16_freeAsmop(left,NULL,ic,TRUE);
10912     pic16_freeAsmop(result,NULL,ic,TRUE);
10913 }
10914
10915 /*-----------------------------------------------------------------*/
10916 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10917 /*-----------------------------------------------------------------*/
10918 static void genPagedPointerGet (operand *left, 
10919                                operand *result, 
10920                                iCode *ic)
10921 {
10922     asmop *aop = NULL;
10923     regs *preg = NULL ;
10924     char *rname ;
10925     sym_link *rtype, *retype;    
10926
10927     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10928
10929     rtype = operandType(result);
10930     retype= getSpec(rtype);
10931     
10932     pic16_aopOp(left,ic,FALSE);
10933
10934   /* if the value is already in a pointer register
10935        then don't need anything more */
10936     if (!AOP_INPREG(AOP(left))) {
10937         /* otherwise get a free pointer register */
10938         aop = newAsmop(0);
10939         preg = getFreePtr(ic,&aop,FALSE);
10940         pic16_emitcode("mov","%s,%s",
10941                 preg->name,
10942                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10943         rname = preg->name ;
10944     } else
10945         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10946     
10947     pic16_freeAsmop(left,NULL,ic,TRUE);
10948     pic16_aopOp (result,ic,TRUE);
10949
10950     /* if bitfield then unpack the bits */
10951     if (IS_BITFIELD(retype)) 
10952         genUnpackBits (result,left,rname,PPOINTER);
10953     else {
10954         /* we have can just get the values */
10955         int size = AOP_SIZE(result);
10956         int offset = 0 ;        
10957         
10958         while (size--) {
10959             
10960             pic16_emitcode("movx","a,@%s",rname);
10961             pic16_aopPut(AOP(result),"a",offset);
10962             
10963             offset++ ;
10964             
10965             if (size)
10966                 pic16_emitcode("inc","%s",rname);
10967         }
10968     }
10969
10970     /* now some housekeeping stuff */
10971     if (aop) {
10972         /* we had to allocate for this iCode */
10973         pic16_freeAsmop(NULL,aop,ic,TRUE);
10974     } else { 
10975         /* we did not allocate which means left
10976            already in a pointer register, then
10977            if size > 0 && this could be used again
10978            we have to point it back to where it 
10979            belongs */
10980         if (AOP_SIZE(result) > 1 &&
10981             !OP_SYMBOL(left)->remat &&
10982             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10983               ic->depth )) {
10984             int size = AOP_SIZE(result) - 1;
10985             while (size--)
10986                 pic16_emitcode("dec","%s",rname);
10987         }
10988     }
10989
10990     /* done */
10991     pic16_freeAsmop(result,NULL,ic,TRUE);
10992     
10993         
10994 }
10995
10996 #if 0
10997 /* This code is not adjusted to PIC16 and fails utterly.
10998  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10999
11000 /*-----------------------------------------------------------------*/
11001 /* genFarPointerGet - gget value from far space                    */
11002 /*-----------------------------------------------------------------*/
11003 static void genFarPointerGet (operand *left,
11004                               operand *result, iCode *ic)
11005 {
11006     int size, offset ;
11007     sym_link *retype = getSpec(operandType(result));
11008
11009     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11010
11011     pic16_aopOp(left,ic,FALSE);
11012
11013     /* if the operand is already in dptr 
11014     then we do nothing else we move the value to dptr */
11015     if (AOP_TYPE(left) != AOP_STR) {
11016         /* if this is remateriazable */
11017         if (AOP_TYPE(left) == AOP_IMMD)
11018             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11019         else { /* we need to get it byte by byte */
11020             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11021             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11022             if (options.model == MODEL_FLAT24)
11023             {
11024                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11025             }
11026         }
11027     }
11028     /* so dptr know contains the address */
11029     pic16_freeAsmop(left,NULL,ic,TRUE);
11030     pic16_aopOp(result,ic,TRUE);
11031
11032     /* if bit then unpack */
11033     if (IS_BITFIELD(retype)) 
11034         genUnpackBits(result,left,"dptr",FPOINTER);
11035     else {
11036         size = AOP_SIZE(result);
11037         offset = 0 ;
11038
11039         while (size--) {
11040             pic16_emitcode("movx","a,@dptr");
11041             pic16_aopPut(AOP(result),"a",offset++);
11042             if (size)
11043                 pic16_emitcode("inc","dptr");
11044         }
11045     }
11046
11047     pic16_freeAsmop(result,NULL,ic,TRUE);
11048 }
11049 #endif
11050
11051 #if 0
11052 /*-----------------------------------------------------------------*/
11053 /* genCodePointerGet - get value from code space                  */
11054 /*-----------------------------------------------------------------*/
11055 static void genCodePointerGet (operand *left,
11056                                 operand *result, iCode *ic)
11057 {
11058     int size, offset ;
11059     sym_link *retype = getSpec(operandType(result));
11060
11061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11062
11063     pic16_aopOp(left,ic,FALSE);
11064
11065     /* if the operand is already in dptr 
11066     then we do nothing else we move the value to dptr */
11067     if (AOP_TYPE(left) != AOP_STR) {
11068         /* if this is remateriazable */
11069         if (AOP_TYPE(left) == AOP_IMMD)
11070             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11071         else { /* we need to get it byte by byte */
11072             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11073             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11074             if (options.model == MODEL_FLAT24)
11075             {
11076                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11077             }
11078         }
11079     }
11080     /* so dptr know contains the address */
11081     pic16_freeAsmop(left,NULL,ic,TRUE);
11082     pic16_aopOp(result,ic,FALSE);
11083
11084     /* if bit then unpack */
11085     if (IS_BITFIELD(retype)) 
11086         genUnpackBits(result,left,"dptr",CPOINTER);
11087     else {
11088         size = AOP_SIZE(result);
11089         offset = 0 ;
11090
11091         while (size--) {
11092             pic16_emitcode("clr","a");
11093             pic16_emitcode("movc","a,@a+dptr");
11094             pic16_aopPut(AOP(result),"a",offset++);
11095             if (size)
11096                 pic16_emitcode("inc","dptr");
11097         }
11098     }
11099
11100     pic16_freeAsmop(result,NULL,ic,TRUE);
11101 }
11102 #endif
11103
11104 #if 0
11105 /*-----------------------------------------------------------------*/
11106 /* genGenPointerGet - gget value from generic pointer space        */
11107 /*-----------------------------------------------------------------*/
11108 static void genGenPointerGet (operand *left,
11109                               operand *result, iCode *ic)
11110 {
11111   int size, offset, lit;
11112   sym_link *retype = getSpec(operandType(result));
11113
11114         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11115         pic16_aopOp(left,ic,FALSE);
11116         pic16_aopOp(result,ic,FALSE);
11117         size = AOP_SIZE(result);
11118
11119         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11120
11121         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11122
11123                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11124                 // load FSR0 from immediate
11125                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11126
11127 //              pic16_loadFSR0( left );
11128
11129                 offset = 0;
11130                 while(size--) {
11131                         if(size) {
11132                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11133                         } else {
11134                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11135                         }
11136                         offset++;
11137                 }
11138                 goto release;
11139
11140         }
11141         else { /* we need to get it byte by byte */
11142                 // set up FSR0 with address from left
11143                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11144                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11145                 
11146                 offset = 0 ;
11147
11148                 while(size--) {
11149                         if(size) {
11150                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11151                         } else {
11152                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11153                         }
11154                         offset++;
11155                 }
11156                 goto release;
11157         }
11158
11159   /* if bit then unpack */
11160         if (IS_BITFIELD(retype)) 
11161                 genUnpackBits(result,left,"BAD",GPOINTER);
11162
11163         release:
11164         pic16_freeAsmop(left,NULL,ic,TRUE);
11165         pic16_freeAsmop(result,NULL,ic,TRUE);
11166
11167 }
11168 #endif
11169
11170
11171 /*-----------------------------------------------------------------*/
11172 /* genGenPointerGet - gget value from generic pointer space        */
11173 /*-----------------------------------------------------------------*/
11174 static void genGenPointerGet (operand *left,
11175                               operand *result, iCode *ic)
11176 {
11177   int size, offset, lit;
11178   sym_link *letype = getSpec(operandType(left));
11179
11180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11181     pic16_aopOp(left,ic,FALSE);
11182     pic16_aopOp(result,ic,TRUE);
11183     size = AOP_SIZE(result);
11184
11185     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11186   
11187     /* if bit then unpack */
11188     if (IS_BITFIELD(letype)) {
11189       genUnpackBits(result,left,"BAD",GPOINTER);
11190       goto release;
11191     }
11192
11193     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11194
11195       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11196       // load FSR0 from immediate
11197       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11198
11199       werror(W_POSSBUG2, __FILE__, __LINE__);
11200
11201       offset = 0;
11202       while(size--) {
11203         if(size) {
11204           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11205         } else {
11206           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11207         }
11208         offset++;
11209       }
11210
11211       goto release;
11212
11213     } else { /* we need to get it byte by byte */
11214
11215       /* set up WREG:PRODL:FSR0L with address from left */
11216       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11217       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11218       pic16_mov2w(AOP(left), 2);
11219       pic16_callGenericPointerRW(0, size);
11220       
11221       assignResultValue(result, 1);
11222       
11223       goto release;
11224     }
11225
11226 release:
11227   pic16_freeAsmop(left,NULL,ic,TRUE);
11228   pic16_freeAsmop(result,NULL,ic,TRUE);
11229 }
11230
11231 /*-----------------------------------------------------------------*/
11232 /* genConstPointerGet - get value from const generic pointer space */
11233 /*-----------------------------------------------------------------*/
11234 static void genConstPointerGet (operand *left,
11235                                 operand *result, iCode *ic)
11236 {
11237   //sym_link *retype = getSpec(operandType(result));
11238   // symbol *albl = newiTempLabel(NULL);        // patch 15
11239   // symbol *blbl = newiTempLabel(NULL);        //
11240   // PIC_OPCODE poc;                            // patch 15
11241   int size;
11242   int offset = 0;
11243
11244   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11245   pic16_aopOp(left,ic,FALSE);
11246   pic16_aopOp(result,ic,TRUE);
11247   size = AOP_SIZE(result);
11248
11249   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11250
11251   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11252
11253   // set up table pointer
11254   if( (AOP_TYPE(left) == AOP_PCODE) 
11255       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11256           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11257     {
11258       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11259       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11260       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11261       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11262       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11263       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11264   } else {
11265     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11266     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11267     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11268   }
11269
11270   while(size--) {
11271     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11272     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11273     offset++;
11274   }
11275     
11276   pic16_freeAsmop(left,NULL,ic,TRUE);
11277   pic16_freeAsmop(result,NULL,ic,TRUE);
11278 }
11279
11280
11281 /*-----------------------------------------------------------------*/
11282 /* genPointerGet - generate code for pointer get                   */
11283 /*-----------------------------------------------------------------*/
11284 static void genPointerGet (iCode *ic)
11285 {
11286   operand *left, *result ;
11287   sym_link *type, *etype;
11288   int p_type;
11289
11290     FENTRY;
11291     
11292     left = IC_LEFT(ic);
11293     result = IC_RESULT(ic) ;
11294
11295     /* depending on the type of pointer we need to
11296     move it to the correct pointer register */
11297     type = operandType(left);
11298     etype = getSpec(type);
11299
11300 #if 0
11301     if (IS_PTR_CONST(type))
11302 #else
11303     if (IS_CODEPTR(type))
11304 #endif
11305       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11306
11307     /* if left is of type of pointer then it is simple */
11308     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11309       p_type = DCL_TYPE(type);
11310     else {
11311       /* we have to go by the storage class */
11312       p_type = PTR_TYPE(SPEC_OCLS(etype));
11313
11314       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11315
11316       if (SPEC_OCLS(etype)->codesp ) {
11317         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11318         //p_type = CPOINTER ;   
11319       } else
11320       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11321         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11322         /*p_type = FPOINTER ;*/ 
11323       } else
11324       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11325         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11326         /* p_type = PPOINTER; */
11327       } else
11328       if (SPEC_OCLS(etype) == idata ) {
11329         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11330         /* p_type = IPOINTER; */
11331       } else {
11332         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11333         /* p_type = POINTER ; */
11334       }
11335     }
11336
11337     /* now that we have the pointer type we assign
11338     the pointer values */
11339     switch (p_type) {
11340       case POINTER:     
11341       case FPOINTER:
11342       case IPOINTER:
11343         genNearPointerGet (left,result,ic);
11344         break;
11345
11346       case PPOINTER:
11347         genPagedPointerGet(left,result,ic);
11348         break;
11349
11350 #if 0
11351       /* PICs do not support FAR pointers... */
11352       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11353       case FPOINTER:
11354         genFarPointerGet (left,result,ic);
11355         break;
11356 #endif
11357
11358       case CPOINTER:
11359         genConstPointerGet (left,result,ic);
11360         //pic16_emitcodePointerGet (left,result,ic);
11361         break;
11362
11363       case GPOINTER:
11364 #if 0
11365       if (IS_PTR_CONST(type))
11366         genConstPointerGet (left,result,ic);
11367       else
11368 #endif
11369         genGenPointerGet (left,result,ic);
11370       break;
11371
11372     default:
11373       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11374               "genPointerGet: illegal pointer type");
11375     
11376     }
11377 }
11378
11379 /*-----------------------------------------------------------------*/
11380 /* genPackBits - generates code for packed bit storage             */
11381 /*-----------------------------------------------------------------*/
11382 static void genPackBits (sym_link    *etype , operand *result,
11383                          operand *right ,
11384                          char *rname, int p_type)
11385 {
11386   int shCnt = 0 ;
11387   int offset = 0  ;
11388   int rLen = 0 ;
11389   int blen, bstr ;   
11390   int shifted_and_masked = 0;
11391   unsigned long lit = (unsigned long)-1;
11392   sym_link *retype;
11393
11394   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11395   blen = SPEC_BLEN(etype);
11396   bstr = SPEC_BSTR(etype);
11397
11398   retype = getSpec(operandType(right));
11399
11400   if(AOP_TYPE(right) == AOP_LIT) {
11401     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11402     
11403     if((blen == 1) && (bstr < 8)) {
11404       /* it is a single bit, so use the appropriate bit instructions */
11405
11406       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11407
11408       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11409         /* workaround to reduce the extra lfsr instruction */
11410         if(lit) {
11411           pic16_emitpcode(POC_BSF,
11412               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11413         } else {
11414           pic16_emitpcode(POC_BCF,
11415               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11416         }
11417       } else {
11418         if (PIC_IS_DATA_PTR(operandType(result))) {
11419           pic16_loadFSR0(result, 0);
11420           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11421               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11422         } else {
11423           /* get old value */
11424           pic16_derefPtr (result, p_type, 0, NULL);
11425           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11426               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11427           /* write back new value */
11428           pic16_derefPtr (result, p_type, 1, NULL);
11429         }
11430       }
11431
11432       return;
11433     }
11434     /* IORLW below is more efficient */
11435     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11436     lit = (lit & ((1UL << blen) - 1)) << bstr;
11437     shifted_and_masked = 1;
11438     offset++;
11439   } else
11440     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11441         && IS_BITFIELD(retype) 
11442         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11443         && (blen == 1)) {
11444       int rblen, rbstr;
11445
11446       rblen = SPEC_BLEN( retype );
11447       rbstr = SPEC_BSTR( retype );
11448
11449       if(IS_BITFIELD(etype)) {
11450         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11451         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11452       } else {
11453         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11454       }
11455
11456       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11457
11458       if(IS_BITFIELD(etype)) {
11459         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11460       } else {
11461         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11462       }
11463
11464       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11465
11466       return;
11467     } else {
11468       /* move right to W */
11469       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11470     }
11471
11472   /* if the bit length is less than or   */
11473   /* it exactly fits a byte then         */
11474   if((shCnt=SPEC_BSTR(etype))
11475       || SPEC_BLEN(etype) <= 8 )  {
11476     int fsr0_setup = 0;
11477
11478     if (blen != 8 || bstr != 0) {
11479       // we need to combine the value with the old value
11480       if(!shifted_and_masked)
11481       {
11482         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11483
11484         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11485             SPEC_BSTR(etype), SPEC_BLEN(etype));
11486
11487         /* shift left acc, do NOT mask the result again */
11488         AccLsh(shCnt, 0);
11489
11490         /* using PRODH as a temporary register here */
11491         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11492       }
11493
11494       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11495         || IS_DIRECT(result)) {
11496         /* access symbol directly */
11497         pic16_mov2w (AOP(result), 0);
11498       } else {
11499         /* get old value */
11500         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11501       }
11502 #if 1
11503       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11504             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11505                             (unsigned char)(0xff >> (8-bstr))) ));
11506       if (!shifted_and_masked) {
11507         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11508       } else {
11509         /* We have the shifted and masked (literal) right value in `lit' */
11510         if (lit != 0)
11511           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11512       }
11513     } // if (blen != 8 || bstr != 0)
11514
11515     /* write new value back */
11516     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11517         || IS_DIRECT(result)) {
11518       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11519     } else {
11520       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11521     }
11522 #endif
11523
11524     return;
11525   }
11526
11527
11528 #if 0
11529   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11530   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11531   exit(EXIT_FAILURE);
11532 #endif
11533
11534
11535   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11536   rLen = SPEC_BLEN(etype)-8;
11537
11538   /* now generate for lengths greater than one byte */
11539   while (1) {
11540     rLen -= 8 ;
11541     if (rLen <= 0 ) {
11542       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11543       break ;
11544     }
11545
11546     switch (p_type) {
11547       case POINTER:
11548         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11549         break;
11550
11551         /*
11552            case FPOINTER:
11553            MOVA(l);
11554            pic16_emitcode("movx","@dptr,a");
11555            break;
11556
11557            case GPOINTER:
11558            MOVA(l);
11559            DEBUGpic16_emitcode(";lcall","__gptrput");
11560            break;  
11561          */
11562       default:
11563         assert(0);
11564     }   
11565
11566
11567     pic16_mov2w(AOP(right), offset++);
11568   }
11569
11570   /* last last was not complete */
11571   if (rLen)   {
11572     /* save the byte & read byte */
11573     switch (p_type) {
11574       case POINTER:
11575         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11576         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11577         break;
11578
11579         /*
11580            case FPOINTER:
11581            pic16_emitcode ("mov","b,a");
11582            pic16_emitcode("movx","a,@dptr");
11583            break;
11584
11585            case GPOINTER:
11586            pic16_emitcode ("push","b");
11587            pic16_emitcode ("push","acc");
11588            pic16_emitcode ("lcall","__gptrget");
11589            pic16_emitcode ("pop","b");
11590            break;
11591          */
11592       default:
11593         assert(0);
11594     }
11595     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11596     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11597     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11598     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11599     //        pic16_emitcode ("orl","a,b");
11600   }
11601
11602   //    if (p_type == GPOINTER)
11603   //        pic16_emitcode("pop","b");
11604
11605   switch (p_type) {
11606
11607     case POINTER:
11608       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11609       //        pic16_emitcode("mov","@%s,a",rname);
11610       break;
11611       /*
11612          case FPOINTER:
11613          pic16_emitcode("movx","@dptr,a");
11614          break;
11615
11616          case GPOINTER:
11617          DEBUGpic16_emitcode(";lcall","__gptrput");
11618          break;                 
11619        */
11620     default:
11621       assert(0);
11622   }
11623
11624   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11625 }
11626
11627 /*-----------------------------------------------------------------*/
11628 /* genDataPointerSet - remat pointer to data space                 */
11629 /*-----------------------------------------------------------------*/
11630 static void genDataPointerSet(operand *right,
11631                               operand *result,
11632                               iCode *ic)
11633 {
11634   int size, offset = 0, resoffset=0 ;
11635
11636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11637     pic16_aopOp(right,ic,FALSE);
11638
11639     size = AOP_SIZE(right);
11640
11641 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11642
11643 #if 0
11644     if ( AOP_TYPE(result) == AOP_PCODE) {
11645       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11646               AOP(result)->aopu.pcop->name,
11647                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11648               PCOR(AOP(result)->aopu.pcop)->instance:
11649               PCOI(AOP(result)->aopu.pcop)->offset);
11650     }
11651 #endif
11652
11653     if(AOP(result)->aopu.pcop->type == PO_DIR)
11654       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11655
11656     while (size--) {
11657       if (AOP_TYPE(right) == AOP_LIT) {
11658         unsigned int lit;
11659
11660           if(!IS_FLOAT(operandType( right )))
11661             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11662           else {
11663             union {
11664               unsigned long lit_int;
11665               float lit_float;
11666             } info;
11667         
11668               /* take care if literal is a float */
11669               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11670               lit = info.lit_int;
11671           }
11672                     lit = lit >> (8*offset);
11673                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11674                 } else {
11675                   pic16_mov2w(AOP(right), offset);
11676                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11677                 }
11678                 offset++;
11679                 resoffset++;
11680         }
11681
11682     pic16_freeAsmop(right,NULL,ic,TRUE);
11683 }
11684
11685
11686
11687 /*-----------------------------------------------------------------*/
11688 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11689 /*-----------------------------------------------------------------*/
11690 static void genNearPointerSet (operand *right,
11691                                operand *result, 
11692                                iCode *ic)
11693 {
11694   asmop *aop = NULL;
11695   sym_link *retype;
11696   sym_link *ptype = operandType(result);
11697   sym_link *resetype;
11698     
11699     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11700     retype= getSpec(operandType(right));
11701     resetype = getSpec(operandType(result));
11702   
11703     pic16_aopOp(result,ic,FALSE);
11704     
11705     /* if the result is rematerializable &
11706      * in data space & not a bit variable */
11707         
11708     /* and result is not a bit variable */
11709     if (AOP_TYPE(result) == AOP_PCODE
11710 //      && AOP_TYPE(result) == AOP_IMMD
11711       && DCL_TYPE(ptype) == POINTER
11712       && !IS_BITFIELD(retype)
11713       && !IS_BITFIELD(resetype)) {
11714
11715         genDataPointerSet (right,result,ic);
11716         pic16_freeAsmop(result,NULL,ic,TRUE);
11717       return;
11718     }
11719
11720     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11721     pic16_aopOp(right,ic,FALSE);
11722     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11723
11724     /* if bitfield then unpack the bits */
11725     if (IS_BITFIELD(resetype)) {
11726       genPackBits (resetype, result, right, NULL, POINTER);
11727     } else {
11728       /* we have can just get the values */
11729       int size = AOP_SIZE(right);
11730       int offset = 0 ;    
11731
11732         pic16_loadFSR0(result, 0);
11733             
11734         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11735         while (size--) {
11736           if (AOP_TYPE(right) == AOP_LIT) {
11737             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11738             if (size) {
11739               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11740             } else {
11741               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11742             }
11743           } else { // no literal
11744             if(size) {
11745               pic16_emitpcode(POC_MOVFF,
11746                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11747                   pic16_popCopyReg(&pic16_pc_postinc0)));
11748             } else {
11749               pic16_emitpcode(POC_MOVFF,
11750                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11751                   pic16_popCopyReg(&pic16_pc_indf0)));
11752             }
11753           }
11754           
11755           offset++;
11756         }
11757     }
11758
11759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11760     /* now some housekeeping stuff */
11761     if (aop) {
11762       /* we had to allocate for this iCode */
11763       pic16_freeAsmop(NULL,aop,ic,TRUE);
11764     } else { 
11765       /* we did not allocate which means left
11766        * already in a pointer register, then
11767        * if size > 0 && this could be used again
11768        * we have to point it back to where it 
11769        * belongs */
11770       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11771       if (AOP_SIZE(right) > 1
11772         && !OP_SYMBOL(result)->remat
11773         && ( OP_SYMBOL(result)->liveTo > ic->seq
11774         || ic->depth )) {
11775
11776           int size = AOP_SIZE(right) - 1;
11777
11778             while (size--)
11779               pic16_emitcode("decf","fsr0,f");
11780               //pic16_emitcode("dec","%s",rname);
11781       }
11782     }
11783
11784     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11785     /* done */
11786 //release:
11787     pic16_freeAsmop(right,NULL,ic,TRUE);
11788     pic16_freeAsmop(result,NULL,ic,TRUE);
11789 }
11790
11791 /*-----------------------------------------------------------------*/
11792 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11793 /*-----------------------------------------------------------------*/
11794 static void genPagedPointerSet (operand *right,
11795                                operand *result, 
11796                                iCode *ic)
11797 {
11798     asmop *aop = NULL;
11799     regs *preg = NULL ;
11800     char *rname , *l;
11801     sym_link *retype;
11802        
11803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11804
11805     retype= getSpec(operandType(right));
11806     
11807     pic16_aopOp(result,ic,FALSE);
11808     
11809     /* if the value is already in a pointer register
11810        then don't need anything more */
11811     if (!AOP_INPREG(AOP(result))) {
11812         /* otherwise get a free pointer register */
11813         aop = newAsmop(0);
11814         preg = getFreePtr(ic,&aop,FALSE);
11815         pic16_emitcode("mov","%s,%s",
11816                 preg->name,
11817                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11818         rname = preg->name ;
11819     } else
11820         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11821     
11822     pic16_freeAsmop(result,NULL,ic,TRUE);
11823     pic16_aopOp (right,ic,FALSE);
11824
11825     /* if bitfield then unpack the bits */
11826     if (IS_BITFIELD(retype)) 
11827         genPackBits (retype,result,right,rname,PPOINTER);
11828     else {
11829         /* we have can just get the values */
11830         int size = AOP_SIZE(right);
11831         int offset = 0 ;        
11832         
11833         while (size--) {
11834             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11835             
11836             MOVA(l);
11837             pic16_emitcode("movx","@%s,a",rname);
11838
11839             if (size)
11840                 pic16_emitcode("inc","%s",rname);
11841
11842             offset++;
11843         }
11844     }
11845     
11846     /* now some housekeeping stuff */
11847     if (aop) {
11848         /* we had to allocate for this iCode */
11849         pic16_freeAsmop(NULL,aop,ic,TRUE);
11850     } else { 
11851         /* we did not allocate which means left
11852            already in a pointer register, then
11853            if size > 0 && this could be used again
11854            we have to point it back to where it 
11855            belongs */
11856         if (AOP_SIZE(right) > 1 &&
11857             !OP_SYMBOL(result)->remat &&
11858             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11859               ic->depth )) {
11860             int size = AOP_SIZE(right) - 1;
11861             while (size--)
11862                 pic16_emitcode("dec","%s",rname);
11863         }
11864     }
11865
11866     /* done */
11867     pic16_freeAsmop(right,NULL,ic,TRUE);
11868     
11869         
11870 }
11871
11872 #if 0
11873 /* This code is not adjusted to PIC16 and fails utterly...
11874  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11875
11876 /*-----------------------------------------------------------------*/
11877 /* genFarPointerSet - set value from far space                     */
11878 /*-----------------------------------------------------------------*/
11879 static void genFarPointerSet (operand *right,
11880                               operand *result, iCode *ic)
11881 {
11882     int size, offset ;
11883     sym_link *retype = getSpec(operandType(right));
11884
11885     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11886     pic16_aopOp(result,ic,FALSE);
11887
11888     /* if the operand is already in dptr 
11889     then we do nothing else we move the value to dptr */
11890     if (AOP_TYPE(result) != AOP_STR) {
11891         /* if this is remateriazable */
11892         if (AOP_TYPE(result) == AOP_IMMD)
11893             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11894         else { /* we need to get it byte by byte */
11895             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11896             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11897             if (options.model == MODEL_FLAT24)
11898             {
11899                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11900             }
11901         }
11902     }
11903     /* so dptr know contains the address */
11904     pic16_freeAsmop(result,NULL,ic,TRUE);
11905     pic16_aopOp(right,ic,FALSE);
11906
11907     /* if bit then unpack */
11908     if (IS_BITFIELD(retype)) 
11909         genPackBits(retype,result,right,"dptr",FPOINTER);
11910     else {
11911         size = AOP_SIZE(right);
11912         offset = 0 ;
11913
11914         while (size--) {
11915             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11916             MOVA(l);
11917             pic16_emitcode("movx","@dptr,a");
11918             if (size)
11919                 pic16_emitcode("inc","dptr");
11920         }
11921     }
11922
11923     pic16_freeAsmop(right,NULL,ic,TRUE);
11924 }
11925 #endif
11926
11927 /*-----------------------------------------------------------------*/
11928 /* genGenPointerSet - set value from generic pointer space         */
11929 /*-----------------------------------------------------------------*/
11930 #if 0
11931 static void genGenPointerSet (operand *right,
11932                               operand *result, iCode *ic)
11933 {
11934         int i, size, offset, lit;
11935         sym_link *retype = getSpec(operandType(right));
11936
11937         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11938
11939         pic16_aopOp(result,ic,FALSE);
11940         pic16_aopOp(right,ic,FALSE);
11941         size = AOP_SIZE(right);
11942         offset = 0;
11943
11944         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11945
11946         /* if the operand is already in dptr 
11947                 then we do nothing else we move the value to dptr */
11948         if (AOP_TYPE(result) != AOP_STR) {
11949                 /* if this is remateriazable */
11950                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11951                 // WARNING: anythig until "else" is untested!
11952                 if (AOP_TYPE(result) == AOP_IMMD) {
11953                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11954                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11955                         // load FSR0 from immediate
11956                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11957                         offset = 0;
11958                         while(size--) {
11959                                 if(size) {
11960                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11961                                 } else {
11962                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11963                                 }
11964                                 offset++;
11965                         }
11966                         goto release;
11967                 }
11968                 else { /* we need to get it byte by byte */
11969                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11970                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11971
11972                         // set up FSR0 with address of result
11973                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11974                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11975
11976                         /* hack hack! see if this the FSR. If so don't load W */
11977                         if(AOP_TYPE(right) != AOP_ACC) {
11978
11979                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11980
11981                                 if(AOP_TYPE(right) == AOP_LIT)
11982                                 {
11983                                         // copy literal
11984                                         // note: pic16_popGet handles sign extension
11985                                         for(i=0;i<size;i++) {
11986                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11987                                                 if(i < size-1)
11988                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11989                                                 else
11990                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11991                                         }
11992                                 } else {
11993                                         // copy regs
11994
11995                                         for(i=0;i<size;i++) {
11996                                                 if(i < size-1)
11997                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11998                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11999                                                 else
12000                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12001                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12002                                         }
12003                                 }
12004                                 goto release;
12005                         } 
12006                         // right = ACC
12007                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12008                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12009                         goto release;
12010         } // if (AOP_TYPE(result) != AOP_IMMD)
12011
12012         } // if (AOP_TYPE(result) != AOP_STR)
12013         /* so dptr know contains the address */
12014
12015
12016         /* if bit then unpack */
12017         if (IS_BITFIELD(retype)) 
12018                 genPackBits(retype,result,right,"dptr",GPOINTER);
12019         else {
12020                 size = AOP_SIZE(right);
12021                 offset = 0 ;
12022
12023                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12024
12025                 // set up FSR0 with address of result
12026                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12027                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12028         
12029                 while (size--) {
12030                         if (AOP_TYPE(right) == AOP_LIT) {
12031                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12032                                 if (size) {
12033                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12034                                 } else {
12035                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12036                                 }
12037                         } else { // no literal
12038                                 if(size) {
12039                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12040                                 } else {
12041                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12042                                 }
12043                         }
12044                         offset++;
12045                 }
12046         }
12047
12048         release:
12049         pic16_freeAsmop(right,NULL,ic,TRUE);
12050         pic16_freeAsmop(result,NULL,ic,TRUE);
12051 }
12052 #endif
12053
12054 static void genGenPointerSet (operand *right,
12055                               operand *result, iCode *ic)
12056 {
12057   int size;
12058   sym_link *retype = getSpec(operandType(result));
12059
12060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12061
12062     pic16_aopOp(result,ic,FALSE);
12063     pic16_aopOp(right,ic,FALSE);
12064     size = AOP_SIZE(right);
12065
12066     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12067
12068
12069     /* if bit then unpack */
12070     if (IS_BITFIELD(retype)) {
12071 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12072       genPackBits(retype,result,right,"dptr",GPOINTER);
12073       goto release;
12074     }
12075
12076     size = AOP_SIZE(right);
12077
12078     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12079
12080
12081     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12082
12083     /* value of right+0 is placed on stack, which will be retrieved
12084      * by the support function thus restoring the stack. The important
12085      * thing is that there is no need to manually restore stack pointer
12086      * here */
12087     pushaop(AOP(right), 0);
12088 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12089     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12090     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12091     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12092     
12093     /* load address to write to in WREG:FSR0H:FSR0L */
12094     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12095                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12096     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12097                                 pic16_popCopyReg(&pic16_pc_prodl)));
12098     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12099     
12100     pic16_callGenericPointerRW(1, size);
12101
12102 release:
12103     pic16_freeAsmop(right,NULL,ic,TRUE);
12104     pic16_freeAsmop(result,NULL,ic,TRUE);
12105 }
12106
12107 /*-----------------------------------------------------------------*/
12108 /* genPointerSet - stores the value into a pointer location        */
12109 /*-----------------------------------------------------------------*/
12110 static void genPointerSet (iCode *ic)
12111 {    
12112   operand *right, *result ;
12113   sym_link *type, *etype;
12114   int p_type;
12115
12116     FENTRY;
12117
12118     right = IC_RIGHT(ic);
12119     result = IC_RESULT(ic) ;
12120
12121     /* depending on the type of pointer we need to
12122     move it to the correct pointer register */
12123     type = operandType(result);
12124     etype = getSpec(type);
12125     
12126     /* if left is of type of pointer then it is simple */
12127     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12128         p_type = DCL_TYPE(type);
12129     }
12130     else {
12131         /* we have to go by the storage class */
12132         p_type = PTR_TYPE(SPEC_OCLS(etype));
12133
12134 /*      if (SPEC_OCLS(etype)->codesp ) { */
12135 /*          p_type = CPOINTER ;  */
12136 /*      } */
12137 /*      else */
12138 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12139 /*              p_type = FPOINTER ; */
12140 /*          else */
12141 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12142 /*                  p_type = PPOINTER ; */
12143 /*              else */
12144 /*                  if (SPEC_OCLS(etype) == idata ) */
12145 /*                      p_type = IPOINTER ; */
12146 /*                  else */
12147 /*                      p_type = POINTER ; */
12148     }
12149
12150     /* now that we have the pointer type we assign
12151     the pointer values */
12152     switch (p_type) {
12153       case POINTER:
12154       case FPOINTER:
12155       case IPOINTER:
12156         genNearPointerSet (right,result,ic);
12157         break;
12158
12159       case PPOINTER:
12160         genPagedPointerSet (right,result,ic);
12161         break;
12162
12163 #if 0
12164       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12165       case FPOINTER:
12166         genFarPointerSet (right,result,ic);
12167         break;
12168 #endif
12169         
12170       case GPOINTER:
12171         genGenPointerSet (right,result,ic);
12172         break;
12173
12174       default:
12175         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12176           "genPointerSet: illegal pointer type");
12177     }
12178 }
12179
12180 /*-----------------------------------------------------------------*/
12181 /* genIfx - generate code for Ifx statement                        */
12182 /*-----------------------------------------------------------------*/
12183 static void genIfx (iCode *ic, iCode *popIc)
12184 {
12185   operand *cond = IC_COND(ic);
12186   int isbit =0;
12187
12188     FENTRY;
12189
12190     pic16_aopOp(cond,ic,FALSE);
12191
12192     /* get the value into acc */
12193     if (AOP_TYPE(cond) != AOP_CRY)
12194       pic16_toBoolean(cond);
12195     else
12196       isbit = 1;
12197     /* the result is now in the accumulator */
12198     pic16_freeAsmop(cond,NULL,ic,TRUE);
12199
12200     /* if there was something to be popped then do it */
12201     if (popIc)
12202       genIpop(popIc);
12203
12204     /* if the condition is  a bit variable */
12205     if (isbit && IS_ITEMP(cond) && 
12206         SPIL_LOC(cond)) {
12207       genIfxJump(ic,"c");
12208       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12209     } else {
12210       if (isbit && !IS_ITEMP(cond))
12211         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12212         else
12213         genIfxJump(ic,"a");
12214     }
12215     ic->generated = 1;
12216 }
12217
12218 /*-----------------------------------------------------------------*/
12219 /* genAddrOf - generates code for address of                       */
12220 /*-----------------------------------------------------------------*/
12221 static void genAddrOf (iCode *ic)
12222 {
12223   operand *result, *left;
12224   int size;
12225   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12226   pCodeOp *pcop0, *pcop1, *pcop2;
12227
12228     FENTRY;
12229
12230     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12231
12232     sym = OP_SYMBOL( IC_LEFT(ic) );
12233     
12234     if(sym->onStack) {
12235       /* get address of symbol on stack */
12236       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12237 #if 0
12238       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12239                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12240 #endif
12241
12242       // operands on stack are accessible via "FSR2 + index" with index
12243       // starting at 2 for arguments and growing from 0 downwards for
12244       // local variables (index == 0 is not assigned so we add one here)
12245       {
12246         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12247
12248           if (soffs <= 0) {
12249             assert (soffs < 0);
12250             soffs++;
12251           } // if
12252
12253           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12254           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12255           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12256           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12257           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12258           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12259           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12260       }
12261
12262       goto release;
12263     }
12264         
12265 //      if(pic16_debug_verbose) {
12266 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12267 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12268 //      }
12269         
12270     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12271     size = AOP_SIZE(IC_RESULT(ic));
12272
12273     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12274     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12275     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12276         
12277     if (size == 3) {
12278       pic16_emitpcode(POC_MOVLW, pcop0);
12279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12280       pic16_emitpcode(POC_MOVLW, pcop1);
12281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12282       pic16_emitpcode(POC_MOVLW, pcop2);
12283       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12284     } else
12285     if (size == 2) {
12286       pic16_emitpcode(POC_MOVLW, pcop0);
12287       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12288       pic16_emitpcode(POC_MOVLW, pcop1);
12289     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12290     } else {
12291       pic16_emitpcode(POC_MOVLW, pcop0);
12292       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12293     }
12294
12295     pic16_freeAsmop(left, NULL, ic, FALSE);
12296 release:
12297     pic16_freeAsmop(result,NULL,ic,TRUE);
12298 }
12299
12300
12301 #if 0
12302 /*-----------------------------------------------------------------*/
12303 /* genFarFarAssign - assignment when both are in far space         */
12304 /*-----------------------------------------------------------------*/
12305 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12306 {
12307     int size = AOP_SIZE(right);
12308     int offset = 0;
12309     char *l ;
12310     /* first push the right side on to the stack */
12311     while (size--) {
12312         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12313         MOVA(l);
12314         pic16_emitcode ("push","acc");
12315     }
12316     
12317     pic16_freeAsmop(right,NULL,ic,FALSE);
12318     /* now assign DPTR to result */
12319     pic16_aopOp(result,ic,FALSE);
12320     size = AOP_SIZE(result);
12321     while (size--) {
12322         pic16_emitcode ("pop","acc");
12323         pic16_aopPut(AOP(result),"a",--offset);
12324     }
12325     pic16_freeAsmop(result,NULL,ic,FALSE);
12326         
12327 }
12328 #endif
12329
12330 /*-----------------------------------------------------------------*/
12331 /* genAssign - generate code for assignment                        */
12332 /*-----------------------------------------------------------------*/
12333 static void genAssign (iCode *ic)
12334 {
12335   operand *result, *right;
12336   sym_link *restype, *rtype;
12337   int size, offset,know_W;
12338   unsigned long lit = 0L;
12339
12340     result = IC_RESULT(ic);
12341     right  = IC_RIGHT(ic) ;
12342
12343     FENTRY;
12344   
12345     /* if they are the same */
12346     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12347       return ;
12348
12349     /* reversed order operands are aopOp'ed so that result operand
12350      * is effective in case right is a stack symbol. This maneauver
12351      * allows to use the _G.resDirect flag later */
12352      pic16_aopOp(result,ic,TRUE);
12353     pic16_aopOp(right,ic,FALSE);
12354
12355     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12356
12357     /* if they are the same registers */
12358     if (pic16_sameRegs(AOP(right),AOP(result)))
12359       goto release;
12360
12361     /* if the result is a bit */
12362     if (AOP_TYPE(result) == AOP_CRY) {
12363       /* if the right size is a literal then
12364          we know what the value is */
12365       if (AOP_TYPE(right) == AOP_LIT) {
12366           
12367         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12368             pic16_popGet(AOP(result),0));
12369
12370         if (((int) operandLitValue(right))) 
12371           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12372               AOP(result)->aopu.aop_dir,
12373               AOP(result)->aopu.aop_dir);
12374         else
12375           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12376               AOP(result)->aopu.aop_dir,
12377               AOP(result)->aopu.aop_dir);
12378         
12379         goto release;
12380       }
12381
12382       /* the right is also a bit variable */
12383       if (AOP_TYPE(right) == AOP_CRY) {
12384         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12385         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12386         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12387
12388         goto release ;
12389       }
12390
12391       /* we need to or */
12392       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12393       pic16_toBoolean(right);
12394       emitSKPZ;
12395       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12396       //pic16_aopPut(AOP(result),"a",0);
12397       goto release ;
12398     }
12399
12400     /* bit variables done */
12401     /* general case */
12402     size = AOP_SIZE(result);
12403     offset = 0 ;
12404
12405   /* bit variables done */
12406   /* general case */
12407   size = AOP_SIZE(result);
12408   restype = operandType(result);
12409   rtype = operandType(right);
12410   offset = 0 ;
12411
12412   if(AOP_TYPE(right) == AOP_LIT) {
12413     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12414     {
12415       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12416
12417       /* patch tag for literals that are cast to pointers */
12418       if (IS_CODEPTR(restype)) {
12419         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12420         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12421       } else {
12422         if (IS_GENPTR(restype))
12423         {
12424           if (IS_CODEPTR(rtype)) {
12425             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12426             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12427           } else if (PIC_IS_DATA_PTR(rtype)) {
12428             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12429             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12430           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12431             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12432           } else if (IS_PTR(rtype)) {
12433             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12434             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12435           }
12436         }
12437       }
12438     } else {
12439       union {
12440         unsigned long lit_int;
12441         float lit_float;
12442       } info;
12443
12444
12445       if(IS_FIXED16X16(operandType(right))) {
12446         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12447       } else {
12448         /* take care if literal is a float */
12449         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12450         lit = info.lit_int;
12451       }
12452     }
12453   }
12454
12455 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12456 //                      sizeof(unsigned long int), sizeof(float));
12457
12458
12459     if (AOP_TYPE(right) == AOP_REG) {
12460       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12461       while (size--) {
12462         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12463       } // while
12464       goto release;
12465     }
12466
12467     /* when do we have to read the program memory?
12468      * - if right itself is a symbol in code space
12469      *   (we don't care what it points to if it's a pointer)
12470      * - AND right is not a function (we would want its address)
12471      */
12472     if(AOP_TYPE(right) != AOP_LIT
12473       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12474       && !IS_FUNC(OP_SYM_TYPE(right))
12475       && !IS_ITEMP(right)) {
12476
12477       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12478       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12479       
12480       // set up table pointer
12481       if(is_LitOp(right)) {
12482 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12483         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12484         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12485         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12486         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12487         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12488         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12489       } else {
12490 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12491         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12492             pic16_popCopyReg(&pic16_pc_tblptrl)));
12493         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12494             pic16_popCopyReg(&pic16_pc_tblptrh)));
12495         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12496             pic16_popCopyReg(&pic16_pc_tblptru)));
12497       }
12498
12499       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12500       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12501       while(size--) {
12502         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12503         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12504             pic16_popGet(AOP(result),offset)));
12505         offset++;
12506       }
12507
12508       /* FIXME: for pointers we need to extend differently (according
12509        * to pointer type DATA/CODE/EEPROM/... :*/
12510       size = getSize(OP_SYM_TYPE(right));
12511       if(AOP_SIZE(result) > size) {
12512         size = AOP_SIZE(result) - size;
12513         while(size--) {
12514           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12515           offset++;
12516         }
12517       }
12518       goto release;
12519     }
12520
12521 #if 0
12522     /* VR - What is this?! */
12523     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12524       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12525       
12526       if(aopIdx(AOP(result),0) == 4) {
12527         /* this is a workaround to save value of right into wreg too,
12528          * value of wreg is going to be used later */
12529         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12530         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12531         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12532         goto release;
12533       } else
12534 //      assert(0);
12535       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12536     }
12537 #endif
12538
12539   know_W=-1;
12540   while (size--) {
12541     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12542     if(AOP_TYPE(right) == AOP_LIT) {
12543       if(lit&0xff) {
12544         if(know_W != (lit&0xff))
12545           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12546         know_W = lit&0xff;
12547         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12548       } else
12549         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12550
12551       lit >>= 8;
12552
12553     } else if (AOP_TYPE(right) == AOP_CRY) {
12554       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12555       if(offset == 0) {
12556         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12557         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12558         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12559       }
12560     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12561         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12562         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12563     } else {
12564       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12565
12566       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12567           if(AOP_TYPE(result) == AOP_ACC) {
12568             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12569           } else
12570           if(AOP_TYPE(right) == AOP_ACC) {
12571             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12572           } else {
12573             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12574           }
12575       }
12576     }
12577       
12578       offset++;
12579     }
12580   
12581 release:
12582   pic16_freeAsmop (right,NULL,ic,FALSE);
12583   pic16_freeAsmop (result,NULL,ic,TRUE);
12584
12585
12586 /*-----------------------------------------------------------------*/
12587 /* genJumpTab - generates code for jump table                       */
12588 /*-----------------------------------------------------------------*/
12589 static void genJumpTab (iCode *ic)
12590 {
12591   symbol *jtab;
12592   char *l;
12593   pCodeOp *jt_offs;
12594   pCodeOp *jt_offs_hi;
12595   pCodeOp *jt_label;
12596
12597     FENTRY;
12598
12599     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12600     /* get the condition into accumulator */
12601     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12602     MOVA(l);
12603     /* multiply by three */
12604     pic16_emitcode("add","a,acc");
12605     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12606
12607     jtab = newiTempLabel(NULL);
12608     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12609     pic16_emitcode("jmp","@a+dptr");
12610     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12611
12612 #if 0
12613     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12614     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12615     emitSKPNC;
12616     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12617     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12618     pic16_emitpLabel(jtab->key);
12619
12620 #else
12621
12622     jt_offs = pic16_popGetTempReg(0);
12623     jt_offs_hi = pic16_popGetTempReg(1);
12624     jt_label = pic16_popGetLabel (jtab->key);
12625     //fprintf (stderr, "Creating jump table...\n");
12626
12627     // calculate offset into jump table (idx * sizeof (GOTO))
12628     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12629     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12630     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12631     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12632     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12633     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12634     pic16_emitpcode(POC_MOVWF , jt_offs);
12635
12636     // prepare PCLATx (set to first entry in jump table)
12637     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12638     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12639     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12640     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12641     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12642
12643     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12644     pic16_emitpcode(POC_ADDWF , jt_offs);
12645     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12646     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12647     emitSKPNC;
12648     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12649
12650     // release temporaries and prepare jump into table (new PCL --> WREG)
12651     pic16_emitpcode(POC_MOVFW , jt_offs);
12652     pic16_popReleaseTempReg (jt_offs_hi, 1);
12653     pic16_popReleaseTempReg (jt_offs, 0);
12654
12655     // jump into the table
12656     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12657
12658     pic16_emitpLabelFORCE(jtab->key);
12659 #endif
12660
12661     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12662 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12663
12664     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12665     /* now generate the jump labels */
12666     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12667          jtab = setNextItem(IC_JTLABELS(ic))) {
12668 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12669         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12670         
12671     }
12672     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12673
12674 }
12675
12676 /*-----------------------------------------------------------------*/
12677 /* genMixedOperation - gen code for operators between mixed types  */
12678 /*-----------------------------------------------------------------*/
12679 /*
12680   TSD - Written for the PIC port - but this unfortunately is buggy.
12681   This routine is good in that it is able to efficiently promote 
12682   types to different (larger) sizes. Unfortunately, the temporary
12683   variables that are optimized out by this routine are sometimes
12684   used in other places. So until I know how to really parse the 
12685   iCode tree, I'm going to not be using this routine :(.
12686 */
12687 static int genMixedOperation (iCode *ic)
12688 {
12689 #if 0
12690   operand *result = IC_RESULT(ic);
12691   sym_link *ctype = operandType(IC_LEFT(ic));
12692   operand *right = IC_RIGHT(ic);
12693   int ret = 0;
12694   int big,small;
12695   int offset;
12696
12697   iCode *nextic;
12698   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12699
12700   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12701
12702   nextic = ic->next;
12703   if(!nextic)
12704     return 0;
12705
12706   nextright = IC_RIGHT(nextic);
12707   nextleft  = IC_LEFT(nextic);
12708   nextresult = IC_RESULT(nextic);
12709
12710   pic16_aopOp(right,ic,FALSE);
12711   pic16_aopOp(result,ic,FALSE);
12712   pic16_aopOp(nextright,  nextic, FALSE);
12713   pic16_aopOp(nextleft,   nextic, FALSE);
12714   pic16_aopOp(nextresult, nextic, FALSE);
12715
12716   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12717
12718     operand *t = right;
12719     right = nextright;
12720     nextright = t; 
12721
12722     pic16_emitcode(";remove right +","");
12723
12724   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12725 /*
12726     operand *t = right;
12727     right = nextleft;
12728     nextleft = t; 
12729 */
12730     pic16_emitcode(";remove left +","");
12731   } else
12732     return 0;
12733
12734   big = AOP_SIZE(nextleft);
12735   small = AOP_SIZE(nextright);
12736
12737   switch(nextic->op) {
12738
12739   case '+':
12740     pic16_emitcode(";optimize a +","");
12741     /* if unsigned or not an integral type */
12742     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12743       pic16_emitcode(";add a bit to something","");
12744     } else {
12745
12746       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12747
12748       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12749         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12750         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12751       } else
12752         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12753
12754       offset = 0;
12755       while(--big) {
12756
12757         offset++;
12758
12759         if(--small) {
12760           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12761             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12762             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12763           }
12764
12765           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12766           emitSKPNC;
12767           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12768                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12769                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12770           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12771           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12772
12773         } else {
12774           pic16_emitcode("rlf","known_zero,w");
12775
12776           /*
12777             if right is signed
12778               btfsc  right,7
12779                addlw ff
12780           */
12781           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12782             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12783             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12784           } else {
12785             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12786           }
12787         }
12788       }
12789       ret = 1;
12790     }
12791   }
12792   ret = 1;
12793
12794 release:
12795   pic16_freeAsmop(right,NULL,ic,TRUE);
12796   pic16_freeAsmop(result,NULL,ic,TRUE);
12797   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12798   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12799   if(ret)
12800     nextic->generated = 1;
12801
12802   return ret;
12803 #else
12804   return 0;
12805 #endif
12806 }
12807 /*-----------------------------------------------------------------*/
12808 /* genCast - gen code for casting                                  */
12809 /*-----------------------------------------------------------------*/
12810 static void genCast (iCode *ic)
12811 {
12812   operand *result = IC_RESULT(ic);
12813   sym_link *ctype = operandType(IC_LEFT(ic));
12814   sym_link *rtype = operandType(IC_RIGHT(ic));
12815   sym_link *restype = operandType(IC_RESULT(ic));
12816   operand *right = IC_RIGHT(ic);
12817   int size, offset ;
12818
12819
12820     FENTRY;
12821
12822         /* if they are equivalent then do nothing */
12823 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12824 //              return ;
12825
12826         pic16_aopOp(result,ic,FALSE);
12827         pic16_aopOp(right,ic,FALSE) ;
12828
12829         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12830
12831
12832         /* if the result is a bit */
12833         if (AOP_TYPE(result) == AOP_CRY) {
12834         
12835                 /* if the right size is a literal then
12836                  * we know what the value is */
12837                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12838
12839                 if (AOP_TYPE(right) == AOP_LIT) {
12840                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12841                                 pic16_popGet(AOP(result),0));
12842
12843                         if (((int) operandLitValue(right))) 
12844                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12845                                         AOP(result)->aopu.aop_dir,
12846                                         AOP(result)->aopu.aop_dir);
12847                         else
12848                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12849                                         AOP(result)->aopu.aop_dir,
12850                                         AOP(result)->aopu.aop_dir);
12851                         goto release;
12852                 }
12853
12854                 /* the right is also a bit variable */
12855                 if (AOP_TYPE(right) == AOP_CRY) {
12856                         emitCLRC;
12857                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12858
12859                         pic16_emitcode("clrc","");
12860                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12861                                 AOP(right)->aopu.aop_dir,
12862                                 AOP(right)->aopu.aop_dir);
12863                         pic16_aopPut(AOP(result),"c",0);
12864                         goto release ;
12865                 }
12866
12867                 /* we need to or */
12868                 if (AOP_TYPE(right) == AOP_REG) {
12869                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12870                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12871                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12872                 }
12873                 pic16_toBoolean(right);
12874                 pic16_aopPut(AOP(result),"a",0);
12875                 goto release ;
12876         }
12877
12878         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12879           int offset = 1;
12880
12881                 size = AOP_SIZE(result);
12882
12883                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12884
12885                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12886                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12887                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12888
12889                 while (size--)
12890                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12891
12892                 goto release;
12893         }
12894
12895         if(IS_BITFIELD(getSpec(restype))
12896           && IS_BITFIELD(getSpec(rtype))) {
12897           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12898         }
12899         
12900         /* port from pic14 to cope with generic pointers */
12901         if (PIC_IS_TAGGED(restype))
12902         {
12903           operand *result = IC_RESULT(ic);
12904           //operand *left = IC_LEFT(ic);
12905           operand *right = IC_RIGHT(ic);
12906           int tag = 0xff;
12907
12908           /* copy common part */
12909           int max, size = AOP_SIZE(result);
12910           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12911           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12912
12913           max = size;
12914           while (size--)
12915           {
12916             pic16_mov2w (AOP(right), size);
12917             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12918           } // while
12919
12920           /* upcast into generic pointer type? */
12921           if (IS_GENPTR(restype)
12922               && !PIC_IS_TAGGED(rtype)
12923               && (AOP_SIZE(result) > max))
12924           {
12925             /* determine appropriate tag for right */
12926             if (PIC_IS_DATA_PTR(rtype))
12927               tag = GPTR_TAG_DATA;
12928             else if (IS_CODEPTR(rtype))
12929               tag = GPTR_TAG_CODE;
12930             else if (PIC_IS_DATA_PTR(ctype)) {
12931               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12932               tag = GPTR_TAG_DATA;
12933             } else if (IS_CODEPTR(ctype)) {
12934               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12935               tag = GPTR_TAG_CODE;
12936             } else if (IS_PTR(rtype)) {
12937               PERFORM_ONCE(weirdcast,
12938               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12939               );
12940               tag = GPTR_TAG_DATA;
12941             } else {
12942               PERFORM_ONCE(weirdcast,
12943               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12944               );
12945               tag = GPTR_TAG_DATA;
12946             }
12947
12948             assert (AOP_SIZE(result) == 3);
12949             /* zero-extend address... */
12950             for (size = max; size < AOP_SIZE(result)-1; size++)
12951               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12952             /* ...and add tag */
12953             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12954           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12955             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12956             for (size = max; size < AOP_SIZE(result)-1; size++)
12957               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12958             /* add __code tag */
12959             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12960           } else if (AOP_SIZE(result) > max) {
12961             /* extend non-pointers */
12962             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12963             pic16_addSign(result, max, 0);
12964           } // if
12965           goto release;
12966         }
12967
12968         /* if they are the same size : or less */
12969         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12970
12971                 /* if they are in the same place */
12972                 if (pic16_sameRegs(AOP(right),AOP(result)))
12973                         goto release;
12974
12975                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12976 #if 0
12977                 if (IS_PTR_CONST(rtype))
12978 #else
12979                 if (IS_CODEPTR(rtype))
12980 #endif
12981                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12982
12983 #if 0
12984                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12985 #else
12986                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12987 #endif
12988                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12989
12990 #if 0
12991                 if(AOP_TYPE(right) == AOP_IMMD) {
12992                   pCodeOp *pcop0, *pcop1, *pcop2;
12993                   symbol *sym = OP_SYMBOL( right );
12994
12995                         size = AOP_SIZE(result);
12996                         /* low */
12997                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12998                         /* high */
12999                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13000                         /* upper */
13001                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13002         
13003                         if (size == 3) {
13004                                 pic16_emitpcode(POC_MOVLW, pcop0);
13005                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13006                                 pic16_emitpcode(POC_MOVLW, pcop1);
13007                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13008                                 pic16_emitpcode(POC_MOVLW, pcop2);
13009                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13010                         } else
13011                         if (size == 2) {
13012                                 pic16_emitpcode(POC_MOVLW, pcop0);
13013                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13014                                 pic16_emitpcode(POC_MOVLW, pcop1);
13015                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13016                         } else {
13017                                 pic16_emitpcode(POC_MOVLW, pcop0);
13018                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13019                         }
13020                 } else
13021 #endif
13022                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13023                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13024                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13025
13026                         if(AOP_SIZE(result) < 2) {
13027                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13028                         } else {
13029                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13030                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13031                         }
13032                 } else {
13033                         /* if they in different places then copy */
13034                         size = AOP_SIZE(result);
13035                         offset = 0 ;
13036                         while (size--) {
13037                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13038                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13039                                 offset++;
13040                         }
13041                 }
13042                 goto release;
13043         }
13044
13045         /* if the result is of type pointer */
13046         if (IS_PTR(ctype)) {
13047           int p_type;
13048           sym_link *type = operandType(right);
13049           sym_link *etype = getSpec(type);
13050
13051                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13052
13053                 /* pointer to generic pointer */
13054                 if (IS_GENPTR(ctype)) {
13055                   char *l = zero;
13056             
13057                         if (IS_PTR(type)) 
13058                                 p_type = DCL_TYPE(type);
13059                         else {
13060                 /* we have to go by the storage class */
13061                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13062
13063 /*              if (SPEC_OCLS(etype)->codesp )  */
13064 /*                  p_type = CPOINTER ;  */
13065 /*              else */
13066 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13067 /*                      p_type = FPOINTER ; */
13068 /*                  else */
13069 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13070 /*                          p_type = PPOINTER; */
13071 /*                      else */
13072 /*                          if (SPEC_OCLS(etype) == idata ) */
13073 /*                              p_type = IPOINTER ; */
13074 /*                          else */
13075 /*                              p_type = POINTER ; */
13076             }
13077                 
13078             /* the first two bytes are known */
13079       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13080             size = GPTRSIZE - 1; 
13081             offset = 0 ;
13082             while (size--) {
13083               if(offset < AOP_SIZE(right)) {
13084                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13085                 pic16_mov2f(AOP(result), AOP(right), offset);
13086 /*
13087                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13088                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13089                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13090                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13091                 } else { 
13092                   
13093                   pic16_aopPut(AOP(result),
13094                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13095                          offset);
13096                 }
13097 */
13098               } else 
13099                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13100               offset++;
13101             }
13102             /* the last byte depending on type */
13103             switch (p_type) {
13104             case IPOINTER:
13105             case POINTER:
13106             case FPOINTER:
13107                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13108                 break;
13109
13110             case CPOINTER:
13111                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13112                 break;
13113
13114             case PPOINTER:
13115               pic16_emitcode(";BUG!? ","%d",__LINE__);
13116                 l = "#0x03";
13117                 break;
13118
13119             case GPOINTER:
13120                 if (GPTRSIZE > AOP_SIZE(right)) {
13121                   // assume __data pointer... THIS MIGHT BE WRONG!
13122                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13123                 } else {
13124                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13125                 }
13126               break;
13127               
13128             default:
13129                 /* this should never happen */
13130                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13131                        "got unknown pointer type");
13132                 exit(1);
13133             }
13134             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13135             goto release ;
13136         }
13137         
13138         
13139         assert( 0 );
13140         /* just copy the pointers */
13141         size = AOP_SIZE(result);
13142         offset = 0 ;
13143         while (size--) {
13144             pic16_aopPut(AOP(result),
13145                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13146                    offset);
13147             offset++;
13148         }
13149         goto release ;
13150     }
13151     
13152
13153
13154     /* so we now know that the size of destination is greater
13155     than the size of the source.
13156     Now, if the next iCode is an operator then we might be
13157     able to optimize the operation without performing a cast.
13158     */
13159     if(genMixedOperation(ic))
13160       goto release;
13161
13162     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13163     
13164     /* we move to result for the size of source */
13165     size = AOP_SIZE(right);
13166     offset = 0 ;
13167
13168     while (size--) {
13169       if(!_G.resDirect)
13170         pic16_mov2f(AOP(result), AOP(right), offset);
13171       offset++;
13172     }
13173
13174     /* now depending on the sign of the destination */
13175     size = AOP_SIZE(result) - AOP_SIZE(right);
13176     /* if unsigned or not an integral type */
13177     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13178       while (size--)
13179         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13180     } else {
13181       /* we need to extend the sign :( */
13182
13183       if(size == 1) {
13184         /* Save one instruction of casting char to int */
13185         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13186         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13187         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13188       } else {
13189         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13190
13191         if(offset)
13192           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13193         else
13194           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13195         
13196         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13197
13198         while (size--)
13199           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13200       }
13201     }
13202
13203 release:
13204     pic16_freeAsmop(right,NULL,ic,TRUE);
13205     pic16_freeAsmop(result,NULL,ic,TRUE);
13206
13207 }
13208
13209 /*-----------------------------------------------------------------*/
13210 /* genDjnz - generate decrement & jump if not zero instrucion      */
13211 /*-----------------------------------------------------------------*/
13212 static int genDjnz (iCode *ic, iCode *ifx)
13213 {
13214     symbol *lbl, *lbl1;
13215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13216
13217     if (!ifx)
13218         return 0;
13219     
13220     /* if the if condition has a false label
13221        then we cannot save */
13222     if (IC_FALSE(ifx))
13223         return 0;
13224
13225     /* if the minus is not of the form 
13226        a = a - 1 */
13227     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13228         !IS_OP_LITERAL(IC_RIGHT(ic)))
13229         return 0;
13230
13231     if (operandLitValue(IC_RIGHT(ic)) != 1)
13232         return 0;
13233
13234     /* if the size of this greater than one then no
13235        saving */
13236     if (getSize(operandType(IC_RESULT(ic))) > 1)
13237         return 0;
13238
13239     /* otherwise we can save BIG */
13240     lbl = newiTempLabel(NULL);
13241     lbl1= newiTempLabel(NULL);
13242
13243     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13244     
13245     if (IS_AOP_PREG(IC_RESULT(ic))) {
13246         pic16_emitcode("dec","%s",
13247                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13248         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13249         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13250     } else {    
13251
13252
13253       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13254       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13255
13256       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13257       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13258
13259     }
13260     
13261     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13262     ifx->generated = 1;
13263     return 1;
13264 }
13265
13266 /*-----------------------------------------------------------------*/
13267 /* genReceive - generate code for a receive iCode                  */
13268 /*-----------------------------------------------------------------*/
13269 static void genReceive (iCode *ic)
13270 {    
13271
13272   FENTRY;
13273
13274 #if 0
13275   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13276         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13277 #endif
13278 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13279
13280   if (isOperandInFarSpace(IC_RESULT(ic))
13281       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13282           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13283
13284     int size = getSize(operandType(IC_RESULT(ic)));
13285     int offset =  pic16_fReturnSizePic - size;
13286
13287       assert( 0 );
13288       while (size--) {
13289         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13290                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13291                       offset++;
13292         }
13293
13294       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13295
13296       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13297       size = AOP_SIZE(IC_RESULT(ic));
13298       offset = 0;
13299       while (size--) {
13300         pic16_emitcode ("pop","acc");
13301         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13302       }
13303   } else {
13304     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13305     _G.accInUse++;
13306     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13307     _G.accInUse--;
13308
13309     /* set pseudo stack pointer to where it should be - dw*/
13310     GpsuedoStkPtr = ic->parmBytes;
13311
13312     /* setting GpsuedoStkPtr has side effects here: */
13313     assignResultValue(IC_RESULT(ic), 0);
13314   }
13315
13316   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13317 }
13318
13319 /*-----------------------------------------------------------------*/
13320 /* genDummyRead - generate code for dummy read of volatiles        */
13321 /*-----------------------------------------------------------------*/
13322 static void
13323 genDummyRead (iCode * ic)
13324 {
13325   operand *op;
13326   int i;
13327
13328   op = IC_RIGHT(ic);
13329   if (op && IS_SYMOP(op)) {
13330     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13331       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13332       return;
13333     }
13334     pic16_aopOp (op, ic, FALSE);
13335     for (i=0; i < AOP_SIZE(op); i++) {
13336       // may need to protect this from the peepholer -- this is not nice but works...
13337       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13338       pic16_mov2w (AOP(op),i);
13339       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13340     } // for i
13341     pic16_freeAsmop (op, NULL, ic, TRUE);
13342   } else if (op) {
13343     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13344   } // if
13345 }
13346
13347 /*-----------------------------------------------------------------*/
13348 /* genpic16Code - generate code for pic16 based controllers        */
13349 /*-----------------------------------------------------------------*/
13350 /*
13351  * At this point, ralloc.c has gone through the iCode and attempted
13352  * to optimize in a way suitable for a PIC. Now we've got to generate
13353  * PIC instructions that correspond to the iCode.
13354  *
13355  * Once the instructions are generated, we'll pass through both the
13356  * peep hole optimizer and the pCode optimizer.
13357  *-----------------------------------------------------------------*/
13358
13359 void genpic16Code (iCode *lic)
13360 {
13361   iCode *ic;
13362   int cln = 0;
13363
13364     lineHead = lineCurr = NULL;
13365
13366     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13367     pic16_addpBlock(pb);
13368
13369 #if 0
13370     /* if debug information required */
13371     if (options.debug && currFunc) {
13372       if (currFunc) {
13373         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13374       }
13375     }
13376 #endif
13377
13378     for (ic = lic ; ic ; ic = ic->next ) {
13379
13380       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13381       if ( cln != ic->lineno ) {
13382         if ( options.debug ) {
13383           debugFile->writeCLine (ic);
13384         }
13385         
13386         if(!options.noCcodeInAsm) {
13387           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13388               printCLine(ic->filename, ic->lineno)));
13389         }
13390
13391         cln = ic->lineno ;
13392       }
13393         
13394       if(options.iCodeInAsm) {
13395         char *l;
13396
13397           /* insert here code to print iCode as comment */
13398           l = Safe_strdup(printILine(ic));
13399           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13400       }
13401
13402       /* if the result is marked as
13403        * spilt and rematerializable or code for
13404        * this has already been generated then
13405        * do nothing */
13406       if (resultRemat(ic) || ic->generated ) 
13407         continue ;
13408         
13409       /* depending on the operation */
13410       switch (ic->op) {
13411         case '!' :
13412           pic16_genNot(ic);
13413           break;
13414             
13415         case '~' :
13416           pic16_genCpl(ic);
13417           break;
13418             
13419         case UNARYMINUS:
13420           genUminus (ic);
13421           break;
13422             
13423         case IPUSH:
13424           genIpush (ic);
13425           break;
13426             
13427         case IPOP:
13428           /* IPOP happens only when trying to restore a 
13429            * spilt live range, if there is an ifx statement
13430            * following this pop then the if statement might
13431            * be using some of the registers being popped which
13432            * would destroy the contents of the register so
13433            * we need to check for this condition and handle it */
13434            if (ic->next
13435              && ic->next->op == IFX
13436              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13437                genIfx (ic->next,ic);
13438           else
13439             genIpop (ic);
13440           break; 
13441             
13442         case CALL:
13443           genCall (ic);
13444           break;
13445             
13446         case PCALL:
13447           genPcall (ic);
13448           break;
13449             
13450         case FUNCTION:
13451           genFunction (ic);
13452           break;
13453             
13454         case ENDFUNCTION:
13455           genEndFunction (ic);
13456           break;
13457             
13458         case RETURN:
13459           genRet (ic);
13460           break;
13461             
13462         case LABEL:
13463           genLabel (ic);
13464           break;
13465             
13466         case GOTO:
13467           genGoto (ic);
13468           break;
13469             
13470         case '+' :
13471           pic16_genPlus (ic) ;
13472           break;
13473             
13474         case '-' :
13475           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13476             pic16_genMinus (ic);
13477           break;
13478
13479         case '*' :
13480           genMult (ic);
13481           break;
13482             
13483         case '/' :
13484           genDiv (ic) ;
13485           break;
13486             
13487         case '%' :
13488           genMod (ic);
13489           break;
13490             
13491         case '>' :
13492           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13493           break;
13494             
13495         case '<' :
13496           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13497           break;
13498             
13499         case LE_OP:
13500         case GE_OP:
13501         case NE_OP:
13502           /* note these two are xlated by algebraic equivalence
13503            * during parsing SDCC.y */
13504           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13505             "got '>=' or '<=' shouldn't have come here");
13506           break;
13507
13508         case EQ_OP:
13509           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13510           break;            
13511             
13512         case AND_OP:
13513           genAndOp (ic);
13514           break;
13515             
13516         case OR_OP:
13517           genOrOp (ic);
13518           break;
13519             
13520         case '^' :
13521           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13522           break;
13523             
13524         case '|' :
13525           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13526           break;
13527             
13528         case BITWISEAND:
13529           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13530           break;
13531             
13532         case INLINEASM:
13533           genInline (ic);
13534           break;
13535             
13536         case RRC:
13537           genRRC (ic);
13538           break;
13539             
13540         case RLC:
13541           genRLC (ic);
13542           break;
13543             
13544         case GETHBIT:
13545           genGetHbit (ic);
13546           break;
13547             
13548         case LEFT_OP:
13549           genLeftShift (ic);
13550           break;
13551             
13552         case RIGHT_OP:
13553           genRightShift (ic);
13554           break;
13555             
13556         case GET_VALUE_AT_ADDRESS:
13557           genPointerGet(ic);
13558           break;
13559             
13560         case '=' :
13561           if (POINTER_SET(ic))
13562             genPointerSet(ic);
13563           else
13564             genAssign(ic);
13565           break;
13566             
13567         case IFX:
13568           genIfx (ic,NULL);
13569           break;
13570             
13571         case ADDRESS_OF:
13572           genAddrOf (ic);
13573           break;
13574             
13575         case JUMPTABLE:
13576           genJumpTab (ic);
13577           break;
13578             
13579         case CAST:
13580           genCast (ic);
13581           break;
13582             
13583         case RECEIVE:
13584           genReceive(ic);
13585           break;
13586             
13587         case SEND:
13588           addSet(&_G.sendSet,ic);
13589           break;
13590
13591         case DUMMY_READ_VOLATILE:
13592           genDummyRead (ic);
13593           break;
13594
13595         default :
13596           ic = ic;
13597       }
13598     }
13599
13600
13601     /* now we are ready to call the
13602        peep hole optimizer */
13603     if (!options.nopeep)
13604       peepHole (&lineHead);
13605
13606     /* now do the actual printing */
13607     printLine (lineHead, codeOutFile);
13608
13609 #ifdef PCODE_DEBUG
13610     DFPRINTF((stderr,"printing pBlock\n\n"));
13611     pic16_printpBlock(stdout,pb);
13612 #endif
13613
13614     return;
13615 }
13616