* src/pic16/gen.c (genFunction, genEndFunction): some
[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         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1292         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1293             /* Don't reuse the new aop */
1294             sym->usl.spillLoc->aop = NULL;
1295         }
1296         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1297         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1298           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1299                                                   getSize(sym->type), 
1300                                                   sym->usl.spillLoc->offset, op);
1301         } else {
1302           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1303           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1304           assert (getSize(sym->type) <= 1);
1305           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1306         }
1307         aop->size = getSize(sym->type);
1308
1309         return;
1310     }
1311
1312     {
1313       sym_link *type = operandType(op);
1314 #if 0
1315       if(IS_PTR_CONST(type)) 
1316 #else
1317       if(IS_CODEPTR(type)) 
1318 #endif
1319         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1320     }
1321
1322     /* must be in a register */
1323     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1324     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1325     aop->size = sym->nRegs;
1326     for ( i = 0 ; i < sym->nRegs ;i++)
1327         aop->aopu.aop_reg[i] = sym->regs[i];
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* pic16_freeAsmop - free up the asmop given to an operand               */
1332 /*----------------------------------------------------------------*/
1333 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1334 {   
1335     asmop *aop ;
1336
1337     if (!op)
1338         aop = aaop;
1339     else 
1340         aop = op->aop;
1341
1342     if (!aop)
1343         return ;
1344
1345     if (aop->freed)
1346         goto dealloc; 
1347
1348     aop->freed = 1;
1349
1350     /* depending on the asmop type only three cases need work AOP_RO
1351        , AOP_R1 && AOP_STK */
1352 #if 1
1353     switch (aop->type) {
1354         case AOP_FSR0 :
1355             if (_G.fsr0Pushed ) {
1356                 if (pop) {
1357                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1358                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1359 //                    pic16_emitcode ("pop","ar0");
1360                     _G.fsr0Pushed--;
1361                 }
1362             }
1363             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1364             break;
1365
1366         case AOP_FSR2 :
1367             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1368             break;
1369
1370         case AOP_R0 :
1371             if (_G.r0Pushed ) {
1372                 if (pop) {
1373                     pic16_emitcode ("pop","ar0");     
1374                     _G.r0Pushed--;
1375                 }
1376             }
1377             bitVectUnSetBit(ic->rUsed,R0_IDX);
1378             break;
1379
1380         case AOP_R1 :
1381             if (_G.r1Pushed ) {
1382                 if (pop) {
1383                     pic16_emitcode ("pop","ar1");
1384                     _G.r1Pushed--;
1385                 }
1386             }
1387             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1388             break;
1389
1390         case AOP_STA:
1391           {
1392             int i;
1393
1394               /* we must store the result on stack */
1395               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1396                 // operands on stack are accessible via "FSR2 + index" with index
1397                 // starting at 2 for arguments and growing from 0 downwards for
1398                 // local variables (index == 0 is not assigned so we add one here)
1399                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1400                 if (soffs <= 0) {
1401                   assert (soffs < 0);
1402                   soffs++;
1403                 } // if
1404                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1405                 for(i=0;i<aop->size;i++) {
1406                   /* initialise for stack access via frame pointer */
1407                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1408                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1409                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1410                 }
1411         
1412                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1413               }
1414
1415               if(!_G.resDirect) {
1416                 for(i=0;i<aop->size;i++) {
1417                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1418
1419                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1420                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1421 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1422                   }
1423                 }
1424                 
1425                 {
1426                   regs *sr;
1427                   
1428                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1429                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1430                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1431                       deleteSetItem( &_G.sregsAllocSet, sr );
1432                     }
1433                 }
1434               }
1435               _G.resDirect = 0;
1436           }
1437           break;
1438 #if 0
1439         case AOP_STK :
1440         {
1441             int sz = aop->size;    
1442             int stk = aop->aopu.aop_stk + aop->size;
1443             bitVectUnSetBit(ic->rUsed,R0_IDX);
1444             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1445
1446             getFreePtr(ic,&aop,FALSE);
1447             
1448             if (options.stack10bit)
1449             {
1450                 /* I'm not sure what to do here yet... */
1451                 /* #STUB */
1452                 fprintf(stderr, 
1453                         "*** Warning: probably generating bad code for "
1454                         "10 bit stack mode.\n");
1455             }
1456             
1457             if (stk) {
1458                 pic16_emitcode ("mov","a,_bp");
1459                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1460                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1461             } else {
1462                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1463             }
1464
1465             while (sz--) {
1466                 pic16_emitcode("pop","acc");
1467                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1468                 if (!sz) break;
1469                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1470             }
1471             op->aop = aop;
1472             pic16_freeAsmop(op,NULL,ic,TRUE);
1473             if (_G.r0Pushed) {
1474                 pic16_emitcode("pop","ar0");
1475                 _G.r0Pushed--;
1476             }
1477
1478             if (_G.r1Pushed) {
1479                 pic16_emitcode("pop","ar1");
1480                 _G.r1Pushed--;
1481             }       
1482         }
1483 #endif
1484
1485     }
1486 #endif
1487
1488 dealloc:
1489     /* all other cases just dealloc */
1490     if (op ) {
1491         op->aop = NULL;
1492         if (IS_SYMOP(op)) {
1493             OP_SYMBOL(op)->aop = NULL;    
1494             /* if the symbol has a spill */
1495             if (SPIL_LOC(op))
1496                 SPIL_LOC(op)->aop = NULL;
1497         }
1498     }
1499 }
1500
1501 /*-----------------------------------------------------------------*/
1502 /* pic16_aopGet - for fetching value of the aop                          */
1503 /*-----------------------------------------------------------------*/
1504 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1505 {
1506     char *s = buffer ;
1507     char *rs;
1508
1509     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1510
1511     /* offset is greater than size then zero */
1512     if (offset > (aop->size - 1) &&
1513         aop->type != AOP_LIT)
1514         return zero;
1515
1516     /* depending on type */
1517     switch (aop->type) {
1518
1519     case AOP_FSR0:
1520     case AOP_FSR2:
1521       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1522       rs = Safe_calloc(1, strlen(s)+1);
1523       strcpy(rs, s);
1524       return (rs);
1525       
1526 #if 0
1527       /* if we need to increment it */
1528       while (offset > aop->coff)
1529         {
1530           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1531           aop->coff++;
1532         }
1533
1534       while (offset < aop->coff)
1535         {
1536           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1537           aop->coff--;
1538         }
1539       aop->coff = offset;
1540       if (aop->paged)
1541         {
1542           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1543           return (dname ? "acc" : "a");
1544         }
1545       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1546       rs = Safe_calloc (1, strlen (s) + 1);
1547       strcpy (rs, s);
1548       return rs;
1549 #endif
1550
1551         
1552     case AOP_IMMD:
1553         if (bit16) 
1554             sprintf (s,"%s",aop->aopu.aop_immd);
1555         else
1556             if (offset) 
1557                 sprintf(s,"(%s >> %d)",
1558                         aop->aopu.aop_immd,
1559                         offset*8);
1560             else
1561                 sprintf(s,"%s",
1562                         aop->aopu.aop_immd);
1563         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1564         rs = Safe_calloc(1,strlen(s)+1);
1565         strcpy(rs,s);   
1566         return rs;
1567         
1568     case AOP_DIR:
1569       if (offset) {
1570         sprintf(s,"(%s + %d)",
1571                 aop->aopu.aop_dir,
1572                 offset);
1573         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1574       } else
1575             sprintf(s,"%s",aop->aopu.aop_dir);
1576         rs = Safe_calloc(1,strlen(s)+1);
1577         strcpy(rs,s);   
1578         return rs;
1579         
1580     case AOP_REG:
1581       return aop->aopu.aop_reg[offset]->name;
1582         
1583     case AOP_CRY:
1584       return aop->aopu.aop_dir;
1585         
1586     case AOP_ACC:
1587         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1588 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1589 //        assert( 0 );
1590 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1591         rs = Safe_strdup("WREG");
1592         return (rs);
1593
1594     case AOP_LIT:
1595         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1596         rs = Safe_calloc(1,strlen(s)+1);
1597         strcpy(rs,s);   
1598         return rs;
1599         
1600     case AOP_STR:
1601         aop->coff = offset ;
1602
1603 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1604 //          dname)
1605 //          return "acc";
1606         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1607           aop->type = AOP_ACC;
1608           return Safe_strdup("_WREG");
1609         }
1610         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1611         
1612         return aop->aopu.aop_str[offset];
1613         
1614     case AOP_PCODE:
1615       {
1616         pCodeOp *pcop = aop->aopu.pcop;
1617         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1618         if(pcop->name) {
1619           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1620           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1621           if (offset) {
1622             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1623           } else {
1624             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1625           }
1626         } else
1627           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1628
1629       }
1630       rs = Safe_calloc(1,strlen(s)+1);
1631       strcpy(rs,s);   
1632       return rs;
1633
1634 #if 0
1635     case AOP_PAGED:
1636       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1637       if (offset) {
1638         sprintf(s,"(%s + %d)",
1639                 aop->aopu.aop_dir,
1640                 offset);
1641       } else
1642             sprintf(s,"%s",aop->aopu.aop_dir);
1643       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644       rs = Safe_calloc(1,strlen(s)+1);
1645       strcpy(rs,s);   
1646       return rs;
1647 #endif
1648
1649     case AOP_STA:
1650         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1651         return (rs);
1652         
1653     case AOP_STK:
1654 //        pCodeOp *pcop = aop->aop
1655         break;
1656
1657     }
1658
1659     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1660     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1661            "aopget got unsupported aop->type");
1662     exit(0);
1663 }
1664
1665
1666
1667 /* lock has the following meaning: When allocating temporary registers
1668  * for stack variables storage, the value of the temporary register is
1669  * saved on stack. Its value is restored at the end. This procedure is
1670  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1671  * a possibility that before a call to pic16_aopOp, a temporary register
1672  * is allocated for a while and it is freed after some time, this will
1673  * mess the stack and values will not be restored properly. So use lock=1
1674  * to allocate temporary registers used internally by the programmer, and
1675  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1676  * to inform the compiler developer about a possible bug. This is an internal
1677  * feature for developing the compiler -- VR */
1678  
1679 int _TempReg_lock = 0;
1680 /*-----------------------------------------------------------------*/
1681 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1682 /*-----------------------------------------------------------------*/
1683 pCodeOp *pic16_popGetTempReg(int lock)
1684 {
1685   pCodeOp *pcop=NULL;
1686   symbol *cfunc;
1687
1688 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1689     if(_TempReg_lock) {
1690 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1691     }
1692     
1693     _TempReg_lock += lock;
1694     
1695     cfunc = currFunc;
1696     currFunc = NULL;
1697
1698 #if 0
1699         {
1700           regs *rr;
1701           int i;
1702
1703                 /* this code might seem better but it does the *same* job with
1704                  * the old code, it all depends on ralloc.c to get a free/unused
1705                  * register */
1706          
1707                 i=0;
1708                 while(i < pic16_nRegs) {
1709                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1710                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1711                         if((!rr || (rr && rr->isFree))
1712                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1713                                 pcop = pic16_newpCodeOpReg( i );
1714                                 PCOR(pcop)->r->wasUsed = 1;
1715                                 PCOR(pcop)->r->isFree = 0;
1716                                 break;
1717                         }
1718                         i++;
1719                 }
1720
1721                 if(pcop) {
1722                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1723                 }
1724         }
1725 #else
1726     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1727     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1728       PCOR(pcop)->r->wasUsed=1;
1729       PCOR(pcop)->r->isFree=0;
1730
1731       /* push value on stack */
1732       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1733     }
1734 #endif
1735
1736     currFunc = cfunc;
1737
1738   return pcop;
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1743 /*                           is not part of f, but don't save if   */
1744 /*                           inside v                              */
1745 /*-----------------------------------------------------------------*/
1746 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1747 {
1748   pCodeOp *pcop=NULL;
1749   symbol *cfunc;
1750   int i;
1751
1752 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1753
1754     if(_TempReg_lock) {
1755 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1756     }
1757
1758     _TempReg_lock += lock;
1759
1760     cfunc = currFunc;
1761     currFunc = NULL;
1762
1763     i = bitVectFirstBit(f);
1764     while(i < 128) {
1765
1766       /* bypass registers that are used by function */
1767       if(!bitVectBitValue(f, i)) {
1768       
1769         /* bypass registers that are already allocated for stack access */
1770         if(!bitVectBitValue(v, i))  {
1771         
1772 //          debugf("getting register rIdx = %d\n", i);
1773           /* ok, get the operand */
1774           pcop = pic16_newpCodeOpReg( i );
1775     
1776           /* should never by NULL */
1777           assert( pcop != NULL );
1778
1779           
1780           /* sanity check */
1781           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1782             int found=0;
1783             
1784               PCOR(pcop)->r->wasUsed=1;
1785               PCOR(pcop)->r->isFree=0;
1786
1787
1788               {
1789                 regs *sr;
1790               
1791                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1792
1793                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1794                       /* already used in previous steps, break */
1795                       found=1;          
1796                       break;
1797                     }
1798                   }
1799               }
1800
1801               /* caller takes care of the following */
1802 //              bitVectSetBit(v, i);
1803
1804               if(!found) {
1805                 /* push value on stack */
1806                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1807                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1808               }
1809           
1810             break;
1811           }
1812         }
1813       }
1814       i++;
1815     }
1816
1817     currFunc = cfunc;
1818
1819   return pcop;
1820 }
1821
1822
1823 /*-----------------------------------------------------------------*/
1824 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1825 /*-----------------------------------------------------------------*/
1826 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1827 {
1828   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1829
1830   _TempReg_lock -= lock;
1831
1832   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1833     PCOR(pcop)->r->isFree = 1;
1834
1835     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1836   }
1837 }
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1840 /*-----------------------------------------------------------------*/
1841 pCodeOp *pic16_popGetLabel(int key)
1842 {
1843
1844   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1845
1846   if(key>max_key)
1847     max_key = key;
1848
1849   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1850 }
1851
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popCopyReg - copy a pcode operator                              */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1856 {
1857   pCodeOpReg *pcor;
1858
1859   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1860   memcpy (pcor, pc, sizeof (pCodeOpReg));
1861   pcor->r->wasUsed = 1;
1862   
1863   //pcor->pcop.type = pc->pcop.type;
1864   if(pc->pcop.name) {
1865     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1866       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1867   } else
1868     pcor->pcop.name = NULL;
1869
1870   //pcor->r = pc->r;
1871   //pcor->rIdx = pc->rIdx;
1872   //pcor->r->wasUsed=1;
1873   //pcor->instance = pc->instance;
1874
1875 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1876
1877   return PCOP(pcor);
1878 }
1879
1880 /*-----------------------------------------------------------------*/
1881 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1882 /*-----------------------------------------------------------------*/
1883 pCodeOp *pic16_popGetLit(int lit)
1884 {
1885   return pic16_newpCodeOpLit(lit);
1886 }
1887
1888 /* Allow for 12 bit literals (LFSR x, <here!>). */
1889 pCodeOp *pic16_popGetLit12(int lit)
1890 {
1891   return pic16_newpCodeOpLit12(lit);
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1898 {
1899   return pic16_newpCodeOpLit2(lit, arg2);
1900 }
1901
1902
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1907 {
1908   return pic16_newpCodeOpImmd(name, offset,index, 0);
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGet - asm operator to pcode operator conversion              */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetWithString(char *str)
1916 {
1917   pCodeOp *pcop;
1918
1919
1920   if(!str) {
1921     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1922     exit (1);
1923   }
1924
1925   pcop = pic16_newpCodeOp(str,PO_STR);
1926
1927   return pcop;
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* pic16_popRegFromString -                                        */
1932 /*-----------------------------------------------------------------*/
1933 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1934 {
1935
1936   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1937   pcop->type = PO_DIR;
1938
1939   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1940   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1941
1942   if(!str)
1943     str = "BAD_STRING";
1944
1945   pcop->name = Safe_calloc(1,strlen(str)+1);
1946   strcpy(pcop->name,str);
1947
1948   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1949
1950   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1951 //  PCOR(pcop)->r->wasUsed = 1;
1952
1953   /* make sure that register doesn't exist,
1954    * and operand isn't NULL
1955    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1956   if((PCOR(pcop)->r == NULL) 
1957     && (op)
1958     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1959 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1960 //              __FUNCTION__, __LINE__, str, size, offset);
1961
1962     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1963     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1964
1965   }
1966   PCOR(pcop)->instance = offset;
1967
1968   return pcop;
1969 }
1970
1971 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1972 {
1973   pCodeOp *pcop;
1974
1975 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1976 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1977         
1978         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1979         PCOR(pcop)->rIdx = rIdx;
1980         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1981         if(!PCOR(pcop)->r)
1982                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1983                 
1984         PCOR(pcop)->r->isFree = 0;
1985         PCOR(pcop)->r->wasUsed = 1;
1986
1987         pcop->type = PCOR(pcop)->r->pc_type;
1988
1989   return pcop;
1990 }
1991
1992 /*---------------------------------------------------------------------------------*/
1993 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1994 /*                 VR 030601                                                       */
1995 /*---------------------------------------------------------------------------------*/
1996 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1997 {
1998   pCodeOpReg2 *pcop2;
1999   pCodeOp *temp;
2000   
2001         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
2002
2003         /* comment the following check, so errors to throw up */
2004 //      if(!pcop2)return NULL;
2005
2006         temp = pic16_popGet(aop_dst, offset);
2007         pcop2->pcop2 = temp;
2008         
2009   return PCOP(pcop2);
2010 }
2011
2012
2013
2014 /*--------------------------------------------------------------------------------.-*/
2015 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2016 /*                  VR 030601 , adapted by Hans Dorn                                */
2017 /*--------------------------------------------------------------------------------.-*/
2018 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2019 {
2020   pCodeOpReg2 *pcop2;
2021  
2022         pcop2 = (pCodeOpReg2 *)src;
2023         pcop2->pcop2 = dst;
2024         
2025         return PCOP(pcop2);
2026 }
2027
2028
2029
2030 /*---------------------------------------------------------------------------------*/
2031 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2032 /*                     movff instruction                                           */
2033 /*---------------------------------------------------------------------------------*/
2034 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2035 {
2036   pCodeOpReg2 *pcop2;
2037
2038         if(!noalloc) {
2039                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2040                 pcop2->pcop2 = pic16_popCopyReg(dst);
2041         } else {
2042                 /* the pCodeOp may be already allocated */
2043                 pcop2 = (pCodeOpReg2 *)(src);
2044                 pcop2->pcop2 = (pCodeOp *)(dst);
2045         }
2046
2047   return PCOP(pcop2);
2048 }
2049
2050
2051 /*-----------------------------------------------------------------*/
2052 /* pic16_popGet - asm operator to pcode operator conversion              */
2053 /*-----------------------------------------------------------------*/
2054 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2055 {
2056 //  char *s = buffer ;
2057 //  char *rs;
2058   pCodeOp *pcop;
2059
2060         FENTRY2;
2061                 /* offset is greater than
2062                  * size then zero */
2063
2064 //    if (offset > (aop->size - 1) &&
2065 //        aop->type != AOP_LIT)
2066 //      return NULL;  //zero;
2067
2068     /* depending on type */
2069     switch (aop->type) {
2070                 case AOP_R0:
2071                 case AOP_R1:
2072                 case AOP_DPTR:
2073                 case AOP_DPTR2:
2074                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2075                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2076                         assert( 0 );
2077                         return NULL;
2078
2079                 case AOP_FSR0:
2080                 case AOP_FSR2:
2081                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2082                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2083                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2084                         PCOR(pcop)->r->wasUsed = 1;
2085                         PCOR(pcop)->r->isFree = 0;
2086       
2087                         PCOR(pcop)->instance = offset;
2088                         pcop->type = PCOR(pcop)->r->pc_type;
2089                         return (pcop);
2090
2091                 case AOP_IMMD:
2092                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2093                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2094
2095                 case AOP_STA:
2096                         /* pCodeOp is already allocated from aopForSym */
2097                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2098                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2099                         return (pcop);
2100       
2101                 case AOP_ACC:
2102                         {
2103                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2104
2105                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2106
2107                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2108         
2109                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2110                                 PCOR(pcop)->rIdx = rIdx;
2111                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2112                                 PCOR(pcop)->r->wasUsed=1;
2113                                 PCOR(pcop)->r->isFree=0;
2114
2115                                 PCOR(pcop)->instance = offset;
2116                                 pcop->type = PCOR(pcop)->r->pc_type;
2117 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2118                                 return pcop;
2119
2120
2121 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2122 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2123
2124 //      assert( 0 );
2125                         }
2126         
2127     case AOP_DIR:
2128       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2129       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2130         
2131 #if 0
2132     case AOP_PAGED:
2133       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2134       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2135 #endif
2136
2137     case AOP_REG:
2138       {
2139         int rIdx;
2140         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2141         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2142
2143         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2144         
2145         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2146 //      pcop->type = PO_GPR_REGISTER;
2147         PCOR(pcop)->rIdx = rIdx;
2148         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2149         PCOR(pcop)->r->wasUsed=1;
2150         PCOR(pcop)->r->isFree=0;
2151
2152         PCOR(pcop)->instance = offset;
2153         pcop->type = PCOR(pcop)->r->pc_type;
2154         
2155         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2156 //      rs = aop->aopu.aop_reg[offset]->name;
2157 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2158         return pcop;
2159       }
2160
2161     case AOP_CRY:
2162         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2163
2164       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2165       PCOR(pcop)->instance = offset;
2166       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2167       //if(PCOR(pcop)->r == NULL)
2168       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2169       return pcop;
2170         
2171     case AOP_LIT:
2172         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2173       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2174
2175     case AOP_STR:
2176       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2177       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2178
2179       /*
2180       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2181       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2182       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2183       pcop->type = PCOR(pcop)->r->pc_type;
2184       pcop->name = PCOR(pcop)->r->name;
2185
2186       return pcop;
2187       */
2188
2189     case AOP_PCODE:
2190       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2191                           __LINE__, 
2192                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2193       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2194       switch( aop->aopu.pcop->type ) {
2195         case PO_DIR: PCOR(pcop)->instance += offset; break;
2196         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2197         case PO_WREG:
2198             assert (offset==0);
2199             break;
2200         default:
2201           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2202           assert( 0 );  /* should never reach here */;
2203       }
2204       return pcop;
2205     }
2206
2207     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2208            "pic16_popGet got unsupported aop->type");
2209     exit(0);
2210 }
2211 /*-----------------------------------------------------------------*/
2212 /* pic16_aopPut - puts a string for a aop                                */
2213 /*-----------------------------------------------------------------*/
2214 void pic16_aopPut (asmop *aop, char *s, int offset)
2215 {
2216     char *d = buffer ;
2217     symbol *lbl ;
2218
2219     return;
2220
2221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2222
2223     if (aop->size && offset > ( aop->size - 1)) {
2224         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2225                "pic16_aopPut got offset > aop->size");
2226         exit(0);
2227     }
2228
2229     /* will assign value to value */
2230     /* depending on where it is ofcourse */
2231     switch (aop->type) {
2232     case AOP_DIR:
2233       if (offset) {
2234         sprintf(d,"(%s + %d)",
2235                 aop->aopu.aop_dir,offset);
2236         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2237
2238       } else
2239             sprintf(d,"%s",aop->aopu.aop_dir);
2240         
2241         if (strcmp(d,s)) {
2242           DEBUGpic16_emitcode(";","%d",__LINE__);
2243           if(strcmp(s,"W"))
2244             pic16_emitcode("movf","%s,w",s);
2245           pic16_emitcode("movwf","%s",d);
2246
2247           if(strcmp(s,"W")) {
2248             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2249             if(offset >= aop->size) {
2250               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2251               break;
2252             } else
2253               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2254           }
2255
2256           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2257
2258
2259         }
2260         break;
2261         
2262     case AOP_REG:
2263       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2264         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2265           /*
2266             if (*s == '@'           ||
2267                 strcmp(s,"r0") == 0 ||
2268                 strcmp(s,"r1") == 0 ||
2269                 strcmp(s,"r2") == 0 ||
2270                 strcmp(s,"r3") == 0 ||
2271                 strcmp(s,"r4") == 0 ||
2272                 strcmp(s,"r5") == 0 ||
2273                 strcmp(s,"r6") == 0 || 
2274                 strcmp(s,"r7") == 0 )
2275                 pic16_emitcode("mov","%s,%s  ; %d",
2276                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2277             else
2278           */
2279
2280           if(strcmp(s,"W")==0 )
2281             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2282
2283           pic16_emitcode("movwf","%s",
2284                    aop->aopu.aop_reg[offset]->name);
2285
2286           if(strcmp(s,zero)==0) {
2287             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2288
2289           } else if(strcmp(s,"W")==0) {
2290             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2291             pcop->type = PO_GPR_REGISTER;
2292
2293             PCOR(pcop)->rIdx = -1;
2294             PCOR(pcop)->r = NULL;
2295
2296             DEBUGpic16_emitcode(";","%d",__LINE__);
2297             pcop->name = Safe_strdup(s);
2298             pic16_emitpcode(POC_MOVFW,pcop);
2299             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2300           } else if(strcmp(s,one)==0) {
2301             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2302             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2303           } else {
2304             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2305           }
2306         }
2307         break;
2308         
2309     case AOP_DPTR:
2310     case AOP_DPTR2:
2311     
2312     if (aop->type == AOP_DPTR2)
2313     {
2314         genSetDPTR(1);
2315     }
2316     
2317         if (aop->code) {
2318             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2319                    "pic16_aopPut writting to code space");
2320             exit(0);
2321         }
2322         
2323         while (offset > aop->coff) {
2324             aop->coff++;
2325             pic16_emitcode ("inc","dptr");
2326         }
2327         
2328         while (offset < aop->coff) {
2329             aop->coff-- ;
2330             pic16_emitcode("lcall","__decdptr");
2331         }
2332         
2333         aop->coff = offset;
2334         
2335         /* if not in accumulater */
2336         MOVA(s);        
2337         
2338         pic16_emitcode ("movx","@dptr,a");
2339         
2340     if (aop->type == AOP_DPTR2)
2341     {
2342         genSetDPTR(0);
2343     }
2344         break;
2345         
2346     case AOP_R0:
2347     case AOP_R1:
2348         while (offset > aop->coff) {
2349             aop->coff++;
2350             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2351         }
2352         while (offset < aop->coff) {
2353             aop->coff-- ;
2354             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2355         }
2356         aop->coff = offset;
2357         
2358         if (aop->paged) {
2359             MOVA(s);           
2360             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2361             
2362         } else
2363             if (*s == '@') {
2364                 MOVA(s);
2365                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2366             } else
2367                 if (strcmp(s,"r0") == 0 ||
2368                     strcmp(s,"r1") == 0 ||
2369                     strcmp(s,"r2") == 0 ||
2370                     strcmp(s,"r3") == 0 ||
2371                     strcmp(s,"r4") == 0 ||
2372                     strcmp(s,"r5") == 0 ||
2373                     strcmp(s,"r6") == 0 || 
2374                     strcmp(s,"r7") == 0 ) {
2375                     char buffer[10];
2376                     sprintf(buffer,"a%s",s);
2377                     pic16_emitcode("mov","@%s,%s",
2378                              aop->aopu.aop_ptr->name,buffer);
2379                 } else
2380                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2381         
2382         break;
2383         
2384     case AOP_STK:
2385         if (strcmp(s,"a") == 0)
2386             pic16_emitcode("push","acc");
2387         else
2388             pic16_emitcode("push","%s",s);
2389         
2390         break;
2391         
2392     case AOP_CRY:
2393         /* if bit variable */
2394         if (!aop->aopu.aop_dir) {
2395             pic16_emitcode("clr","a");
2396             pic16_emitcode("rlc","a");
2397         } else {
2398             if (s == zero) 
2399                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2400             else
2401                 if (s == one)
2402                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2403                 else
2404                     if (!strcmp(s,"c"))
2405                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2406                     else {
2407                         lbl = newiTempLabel(NULL);
2408                         
2409                         if (strcmp(s,"a")) {
2410                             MOVA(s);
2411                         }
2412                         pic16_emitcode("clr","c");
2413                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2414                         pic16_emitcode("cpl","c");
2415                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2416                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2417                     }
2418         }
2419         break;
2420         
2421     case AOP_STR:
2422         aop->coff = offset;
2423         if (strcmp(aop->aopu.aop_str[offset],s))
2424             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2425         break;
2426         
2427     case AOP_ACC:
2428         aop->coff = offset;
2429         if (!offset && (strcmp(s,"acc") == 0))
2430             break;
2431         
2432         if (strcmp(aop->aopu.aop_str[offset],s))
2433             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2434         break;
2435
2436     default :
2437         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2438 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2439 //             "pic16_aopPut got unsupported aop->type");
2440 //      exit(0);    
2441     }    
2442
2443 }
2444
2445 /*-----------------------------------------------------------------*/
2446 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2447 /*-----------------------------------------------------------------*/
2448 void pic16_mov2w (asmop *aop, int offset)
2449 {
2450   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2451
2452   if(is_LitAOp(aop))
2453     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2454   else
2455     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2456 }
2457
2458 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2459 {
2460   if(is_LitAOp(src)) {
2461     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2462     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2463   } else {
2464     if(pic16_sameRegsOfs(src, dst, offset))return;
2465     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2466                       pic16_popGet(dst, offset)));
2467   }
2468 }
2469
2470 static void pic16_movLit2f(pCodeOp *pc, int lit)
2471 {
2472   if (0 == (lit & 0x00ff))
2473   {
2474     pic16_emitpcode (POC_CLRF, pc);
2475   } else if (0xff == (lit & 0x00ff))
2476   {
2477     pic16_emitpcode (POC_SETF, pc);
2478   } else {
2479     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2480     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2481   }
2482 }
2483
2484 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2485 {
2486   if(is_LitAOp(src)) {
2487     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2488     pic16_emitpcode(POC_MOVWF, dst);
2489   } else {
2490     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2491   }
2492 }
2493
2494 void pic16_testStackOverflow(void)
2495 {
2496 #define GSTACK_TEST_NAME        "_gstack_test"
2497
2498   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2499   
2500   {
2501     symbol *sym;
2502
2503       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2504       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2505 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2506       checkAddSym(&externs, sym);
2507   }
2508
2509 }
2510
2511 /* push pcop into stack */
2512 void pic16_pushpCodeOp(pCodeOp *pcop)
2513 {
2514 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2515   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2516   if(pic16_options.gstack)
2517     pic16_testStackOverflow();
2518     
2519 }
2520
2521 /* pop pcop from stack */
2522 void pic16_poppCodeOp(pCodeOp *pcop)
2523 {
2524   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2525   if(pic16_options.gstack)
2526     pic16_testStackOverflow();
2527 }
2528
2529
2530 /*-----------------------------------------------------------------*/
2531 /* pushw - pushes wreg to stack                                    */
2532 /*-----------------------------------------------------------------*/
2533 void pushw(void)
2534 {
2535   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2536   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2537   if(pic16_options.gstack)
2538     pic16_testStackOverflow();
2539 }
2540
2541                 
2542 /*-----------------------------------------------------------------*/
2543 /* pushaop - pushes aop to stack                                   */
2544 /*-----------------------------------------------------------------*/
2545 void pushaop(asmop *aop, int offset)
2546 {
2547   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548
2549   if(_G.resDirect)return;
2550   
2551   if(is_LitAOp(aop)) {
2552     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2553     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2554   } else {
2555     pic16_emitpcode(POC_MOVFF,
2556       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2557   }
2558
2559   if(pic16_options.gstack)
2560     pic16_testStackOverflow();
2561 }
2562
2563 /*-----------------------------------------------------------------*/
2564 /* popaop - pops aop from stack                                    */
2565 /*-----------------------------------------------------------------*/
2566 void popaop(asmop *aop, int offset)
2567 {
2568   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2569   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2570   if(pic16_options.gstack)
2571     pic16_testStackOverflow();
2572 }
2573
2574 void popaopidx(asmop *aop, int offset, int index)
2575 {
2576   int ofs=1;
2577
2578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2579
2580     if(STACK_MODEL_LARGE)ofs++;
2581
2582     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2583     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2584     if(pic16_options.gstack)
2585       pic16_testStackOverflow();
2586 }
2587
2588 #if !(USE_GENERIC_SIGNED_SHIFT)
2589 /*-----------------------------------------------------------------*/
2590 /* reAdjustPreg - points a register back to where it should        */
2591 /*-----------------------------------------------------------------*/
2592 static void reAdjustPreg (asmop *aop)
2593 {
2594     int size ;
2595
2596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2597     aop->coff = 0;
2598     if ((size = aop->size) <= 1)
2599         return ;
2600     size-- ;
2601     switch (aop->type) {
2602         case AOP_R0 :
2603         case AOP_R1 :
2604             while (size--)
2605                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2606             break;          
2607         case AOP_DPTR :
2608         case AOP_DPTR2:
2609             if (aop->type == AOP_DPTR2)
2610             {
2611                 genSetDPTR(1);
2612             } 
2613             while (size--)
2614             {
2615                 pic16_emitcode("lcall","__decdptr");
2616             }
2617                 
2618             if (aop->type == AOP_DPTR2)
2619             {
2620                 genSetDPTR(0);
2621             }                
2622             break;  
2623
2624     }   
2625
2626 }
2627 #endif
2628
2629 #if 0
2630 /*-----------------------------------------------------------------*/
2631 /* opIsGptr: returns non-zero if the passed operand is             */   
2632 /* a generic pointer type.                                         */
2633 /*-----------------------------------------------------------------*/ 
2634 static int opIsGptr(operand *op)
2635 {
2636     sym_link *type = operandType(op);
2637     
2638     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2639     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2640     {
2641         return 1;
2642     }
2643     return 0;        
2644 }
2645 #endif
2646
2647 /*-----------------------------------------------------------------*/
2648 /* pic16_getDataSize - get the operand data size                         */
2649 /*-----------------------------------------------------------------*/
2650 int pic16_getDataSize(operand *op)
2651 {
2652     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2653
2654
2655     return AOP_SIZE(op);
2656
2657     // tsd- in the pic port, the genptr size is 1, so this code here
2658     // fails. ( in the 8051 port, the size was 4).
2659 #if 0
2660     int size;
2661     size = AOP_SIZE(op);
2662     if (size == GPTRSIZE)
2663     {
2664         sym_link *type = operandType(op);
2665         if (IS_GENPTR(type))
2666         {
2667             /* generic pointer; arithmetic operations
2668              * should ignore the high byte (pointer type).
2669              */
2670             size--;
2671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2672         }
2673     }
2674     return size;
2675 #endif
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outAcc - output Acc                                             */
2680 /*-----------------------------------------------------------------*/
2681 void pic16_outAcc(operand *result)
2682 {
2683   int size,offset;
2684   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2685   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2686
2687
2688   size = pic16_getDataSize(result);
2689   if(size){
2690     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2691     size--;
2692     offset = 1;
2693     /* unsigned or positive */
2694     while(size--)
2695       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2696   }
2697
2698 }
2699
2700 /*-----------------------------------------------------------------*/
2701 /* pic16_outBitC - output a bit C                                  */
2702 /*                 Move to result the value of Carry flag -- VR    */
2703 /*-----------------------------------------------------------------*/
2704 void pic16_outBitC(operand *result)
2705 {
2706   int i;
2707
2708     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2709
2710     /* if the result is bit */
2711     if (AOP_TYPE(result) == AOP_CRY) {
2712         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2713         pic16_aopPut(AOP(result),"c",0);
2714     } else {
2715
2716         i = AOP_SIZE(result);
2717         while(i--) {
2718                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2719         }
2720         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2721     }
2722 }
2723
2724 /*-----------------------------------------------------------------*/
2725 /* pic16_outBitOp - output a bit from Op                           */
2726 /*                 Move to result the value of set/clr op -- VR    */
2727 /*-----------------------------------------------------------------*/
2728 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2729 {
2730   int i;
2731
2732     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2733
2734     /* if the result is bit */
2735     if (AOP_TYPE(result) == AOP_CRY) {
2736         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2737         pic16_aopPut(AOP(result),"c",0);
2738     } else {
2739
2740         i = AOP_SIZE(result);
2741         while(i--) {
2742                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2743         }
2744         pic16_emitpcode(POC_RRCF, pcop);          
2745         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2746     }
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2751 /*-----------------------------------------------------------------*/
2752 void pic16_toBoolean(operand *oper)
2753 {
2754     int size = AOP_SIZE(oper) - 1;
2755     int offset = 1;
2756
2757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2758
2759     if ( AOP_TYPE(oper) != AOP_ACC) {
2760       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2761     }
2762     while (size--) {
2763       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2764     }
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* genUminusFloat - unary minus for floating points                */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminusFloat(operand *op,operand *result)
2771 {
2772   int size ,offset =0 ;
2773   
2774     FENTRY;
2775     /* for this we just need to flip the 
2776     first it then copy the rest in place */
2777     size = AOP_SIZE(op);
2778     assert( size == AOP_SIZE(result) );
2779
2780     while(size--) {
2781       pic16_mov2f(AOP(result), AOP(op), offset);
2782       offset++;
2783     }
2784     
2785     /* toggle the MSB's highest bit */
2786     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2787 }
2788
2789 /*-----------------------------------------------------------------*/
2790 /* genUminus - unary minus code generation                         */
2791 /*-----------------------------------------------------------------*/
2792 static void genUminus (iCode *ic)
2793 {
2794   int size, i;
2795   sym_link *optype, *rtype;
2796   symbol *label;
2797   int needLabel=0;
2798
2799     FENTRY;     
2800     
2801     /* assign asmops */
2802     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2803     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2804
2805     /* if both in bit space then special case */
2806     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2807       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2808         
2809         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2810         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2811         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2812         goto release; 
2813     } 
2814
2815     optype = operandType(IC_LEFT(ic));
2816     rtype = operandType(IC_RESULT(ic));
2817
2818
2819     /* if float then do float stuff */
2820     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2821       if(IS_FIXED(optype))
2822         debugf("implement fixed16x16 type\n", 0);
2823         
2824         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2825         goto release;
2826     }
2827
2828     /* otherwise subtract from zero by taking the 2's complement */
2829     size = AOP_SIZE(IC_LEFT(ic));
2830     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2831     label = newiTempLabel ( NULL );
2832     
2833     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2834       for (i=size-1; i > 0; i--) {
2835         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2836       } // for
2837       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2838       for (i=1; i < size; i++) {
2839         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2840         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2841       } // for
2842     } else {
2843       for (i=size-1; i >= 0; i--) {
2844         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2846       } // for
2847       if (size > 1) {
2848         for (i=0; i < size-2; i++) {
2849           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2850           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2851         } // for
2852         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2853       } // if
2854       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2855     }
2856     if (needLabel)
2857       pic16_emitpLabel (label->key);
2858
2859 release:
2860     /* release the aops */
2861     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2862     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2863 }
2864
2865 #if 0
2866 /*-----------------------------------------------------------------*/
2867 /* saveRegisters - will look for a call and save the registers     */
2868 /*-----------------------------------------------------------------*/
2869 static void saveRegisters(iCode *lic) 
2870 {
2871     int i;
2872     iCode *ic;
2873     bitVect *rsave;
2874     sym_link *dtype;
2875
2876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2877     /* look for call */
2878     for (ic = lic ; ic ; ic = ic->next) 
2879         if (ic->op == CALL || ic->op == PCALL)
2880             break;
2881
2882     if (!ic) {
2883         fprintf(stderr,"found parameter push with no function call\n");
2884         return ;
2885     }
2886
2887     /* if the registers have been saved already then
2888     do nothing */
2889     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2890         return ;
2891
2892     /* find the registers in use at this time 
2893     and push them away to safety */
2894     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2895                           ic->rUsed);
2896
2897     ic->regsSaved = 1;
2898     if (options.useXstack) {
2899         if (bitVectBitValue(rsave,R0_IDX))
2900             pic16_emitcode("mov","b,r0");
2901         pic16_emitcode("mov","r0,%s",spname);
2902         for (i = 0 ; i < pic16_nRegs ; i++) {
2903             if (bitVectBitValue(rsave,i)) {
2904                 if (i == R0_IDX)
2905                     pic16_emitcode("mov","a,b");
2906                 else
2907                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2908                 pic16_emitcode("movx","@r0,a");
2909                 pic16_emitcode("inc","r0");
2910             }
2911         }
2912         pic16_emitcode("mov","%s,r0",spname);
2913         if (bitVectBitValue(rsave,R0_IDX))
2914             pic16_emitcode("mov","r0,b");           
2915     }// else
2916     //for (i = 0 ; i < pic16_nRegs ; i++) {
2917     //    if (bitVectBitValue(rsave,i))
2918     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2919     //}
2920
2921     dtype = operandType(IC_LEFT(ic));
2922     if (currFunc && dtype && 
2923         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2924         IFFUNC_ISISR(currFunc->type) &&
2925         !ic->bankSaved) 
2926
2927         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2928
2929 }
2930 /*-----------------------------------------------------------------*/
2931 /* unsaveRegisters - pop the pushed registers                      */
2932 /*-----------------------------------------------------------------*/
2933 static void unsaveRegisters (iCode *ic)
2934 {
2935     int i;
2936     bitVect *rsave;
2937
2938     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2939     /* find the registers in use at this time 
2940     and push them away to safety */
2941     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2942                           ic->rUsed);
2943     
2944     if (options.useXstack) {
2945         pic16_emitcode("mov","r0,%s",spname);   
2946         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2947             if (bitVectBitValue(rsave,i)) {
2948                 pic16_emitcode("dec","r0");
2949                 pic16_emitcode("movx","a,@r0");
2950                 if (i == R0_IDX)
2951                     pic16_emitcode("mov","b,a");
2952                 else
2953                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2954             }       
2955
2956         }
2957         pic16_emitcode("mov","%s,r0",spname);
2958         if (bitVectBitValue(rsave,R0_IDX))
2959             pic16_emitcode("mov","r0,b");
2960     } //else
2961     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2962     //    if (bitVectBitValue(rsave,i))
2963     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2964     //}
2965
2966 }  
2967 #endif
2968
2969 #if 0  // patch 14
2970 /*-----------------------------------------------------------------*/
2971 /* pushSide -                                                      */
2972 /*-----------------------------------------------------------------*/
2973 static void pushSide(operand * oper, int size)
2974 {
2975         int offset = 0;
2976     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2977         while (size--) {
2978                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2979                 if (AOP_TYPE(oper) != AOP_REG &&
2980                     AOP_TYPE(oper) != AOP_DIR &&
2981                     strcmp(l,"a") ) {
2982                         pic16_emitcode("mov","a,%s",l);
2983                         pic16_emitcode("push","acc");
2984                 } else
2985                         pic16_emitcode("push","%s",l);
2986         }
2987 }
2988 #endif // patch 14
2989
2990 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2991 {
2992   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2993     pic16_emitpcode(POC_MOVFW, src);
2994     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2995   } else {
2996     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2997         src, pic16_popGet(AOP(op), offset)));
2998   }
2999 }
3000
3001
3002 /*-----------------------------------------------------------------*/
3003 /* assignResultValue - assign results to oper, rescall==1 is       */
3004 /*                     called from genCall() or genPcall()         */
3005 /*-----------------------------------------------------------------*/
3006 static void assignResultValue(operand * oper, int rescall)
3007 {
3008   int size = AOP_SIZE(oper);
3009   int offset=0;
3010   
3011     FENTRY2;
3012 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3013     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3014
3015     if(rescall) {
3016       /* assign result from a call/pcall function() */
3017                 
3018       /* function results are stored in a special order,
3019        * see top of file with Function return policy, or manual */
3020
3021       if(size <= 4) {
3022         /* 8-bits, result in WREG */
3023         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3024                         
3025         if(size>1) {
3026           /* 16-bits, result in PRODL:WREG */
3027           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3028         }
3029                         
3030         if(size>2) {
3031           /* 24-bits, result in PRODH:PRODL:WREG */
3032           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3033         }
3034                         
3035         if(size>3) {
3036           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3037           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3038         }
3039       
3040       } else {
3041         /* >32-bits, result on stack, and FSR0 points to beginning.
3042          * Fix stack when done */
3043         /* FIXME FIXME */
3044 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3045         while (size--) {
3046 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3047 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3048                 
3049           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3050           GpsuedoStkPtr++;
3051         }
3052                         
3053         /* fix stack */
3054         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3055         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3056         if(STACK_MODEL_LARGE) {
3057           emitSKPNC;
3058           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3059         }
3060       }                 
3061     } else {
3062       int areg = 0;             /* matching argument register */
3063       
3064 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3065       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3066
3067
3068       /* its called from genReceive (probably) -- VR */
3069       /* I hope this code will not be called from somewhere else in the future! 
3070        * We manually set the pseudo stack pointer in genReceive. - dw
3071        */
3072       if(!GpsuedoStkPtr && _G.useWreg) {
3073 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3074
3075         /* The last byte in the assignment is in W */
3076         if(areg <= GpsuedoStkPtr) {
3077           size--;
3078           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3079           offset++;
3080 //          debugf("receive from WREG\n", 0);
3081         }
3082         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3083       }
3084 //      GpsuedoStkPtr++;
3085       _G.stack_lat = AOP_SIZE(oper)-1;
3086
3087       while (size) {
3088         size--;
3089         GpsuedoStkPtr++;
3090         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3091 //        debugf("receive from STACK\n", 0);
3092         offset++;
3093       }
3094     }
3095 }
3096
3097
3098 /*-----------------------------------------------------------------*/
3099 /* genIpush - generate code for pushing this gets a little complex */
3100 /*-----------------------------------------------------------------*/
3101 static void genIpush (iCode *ic)
3102 {
3103 //  int size, offset=0;
3104
3105   FENTRY;
3106   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3107
3108   if(ic->parmPush) {
3109     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3110
3111     /* send to stack as normal */
3112     addSet(&_G.sendSet,ic);
3113 //    addSetHead(&_G.sendSet,ic);
3114     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3115   }
3116
3117         
3118 #if 0
3119     int size, offset = 0 ;
3120     char *l;
3121
3122
3123     /* if this is not a parm push : ie. it is spill push 
3124     and spill push is always done on the local stack */
3125     if (!ic->parmPush) {
3126
3127         /* and the item is spilt then do nothing */
3128         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3129             return ;
3130
3131         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3132         size = AOP_SIZE(IC_LEFT(ic));
3133         /* push it on the stack */
3134         while(size--) {
3135             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3136             if (*l == '#') {
3137                 MOVA(l);
3138                 l = "acc";
3139             }
3140             pic16_emitcode("push","%s",l);
3141         }
3142         return ;        
3143     }
3144
3145     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3146 #endif
3147 }
3148
3149 /*-----------------------------------------------------------------*/
3150 /* genIpop - recover the registers: can happen only for spilling   */
3151 /*-----------------------------------------------------------------*/
3152 static void genIpop (iCode *ic)
3153 {
3154   FENTRY;
3155   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3156 #if 0
3157     int size,offset ;
3158
3159
3160     /* if the temp was not pushed then */
3161     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3162         return ;
3163
3164     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3165     size = AOP_SIZE(IC_LEFT(ic));
3166     offset = (size-1);
3167     while (size--) 
3168         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3169                                    FALSE,TRUE));
3170
3171     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3172 #endif
3173 }
3174
3175 #if 0
3176 /*-----------------------------------------------------------------*/
3177 /* unsaverbank - restores the resgister bank from stack            */
3178 /*-----------------------------------------------------------------*/
3179 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3180 {
3181   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3182 #if 0
3183     int i;
3184     asmop *aop ;
3185     regs *r = NULL;
3186
3187     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3188     if (popPsw) {
3189         if (options.useXstack) {
3190             aop = newAsmop(0);
3191             r = getFreePtr(ic,&aop,FALSE);
3192             
3193             
3194             pic16_emitcode("mov","%s,_spx",r->name);
3195             pic16_emitcode("movx","a,@%s",r->name);
3196             pic16_emitcode("mov","psw,a");
3197             pic16_emitcode("dec","%s",r->name);
3198             
3199         }else
3200             pic16_emitcode ("pop","psw");
3201     }
3202
3203     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3204         if (options.useXstack) {       
3205             pic16_emitcode("movx","a,@%s",r->name);
3206             //pic16_emitcode("mov","(%s+%d),a",
3207             //       regspic16[i].base,8*bank+regspic16[i].offset);
3208             pic16_emitcode("dec","%s",r->name);
3209
3210         } else 
3211           pic16_emitcode("pop",""); //"(%s+%d)",
3212         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3213     }
3214
3215     if (options.useXstack) {
3216
3217         pic16_emitcode("mov","_spx,%s",r->name);
3218         pic16_freeAsmop(NULL,aop,ic,TRUE);
3219
3220     }
3221 #endif 
3222 }
3223
3224 /*-----------------------------------------------------------------*/
3225 /* saverbank - saves an entire register bank on the stack          */
3226 /*-----------------------------------------------------------------*/
3227 static void saverbank (int bank, iCode *ic, bool pushPsw)
3228 {
3229   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3230 #if 0
3231     int i;
3232     asmop *aop ;
3233     regs *r = NULL;
3234
3235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3236     if (options.useXstack) {
3237
3238         aop = newAsmop(0);
3239         r = getFreePtr(ic,&aop,FALSE);  
3240         pic16_emitcode("mov","%s,_spx",r->name);
3241
3242     }
3243
3244     for (i = 0 ; i < pic16_nRegs ;i++) {
3245         if (options.useXstack) {
3246             pic16_emitcode("inc","%s",r->name);
3247             //pic16_emitcode("mov","a,(%s+%d)",
3248             //         regspic16[i].base,8*bank+regspic16[i].offset);
3249             pic16_emitcode("movx","@%s,a",r->name);           
3250         } else 
3251           pic16_emitcode("push","");// "(%s+%d)",
3252                      //regspic16[i].base,8*bank+regspic16[i].offset);
3253     }
3254     
3255     if (pushPsw) {
3256         if (options.useXstack) {
3257             pic16_emitcode("mov","a,psw");
3258             pic16_emitcode("movx","@%s,a",r->name);     
3259             pic16_emitcode("inc","%s",r->name);
3260             pic16_emitcode("mov","_spx,%s",r->name);       
3261             pic16_freeAsmop (NULL,aop,ic,TRUE);
3262             
3263         } else
3264             pic16_emitcode("push","psw");
3265         
3266         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3267     }
3268     ic->bankSaved = 1;
3269 #endif
3270 }
3271 #endif  /* 0 */
3272
3273
3274 static int wparamCmp(void *p1, void *p2)
3275 {
3276   return (!strcmp((char *)p1, (char *)p2));
3277 }
3278
3279 int inWparamList(char *s)
3280 {
3281   return isinSetWith(wparamList, s, wparamCmp);
3282
3283
3284
3285 /*-----------------------------------------------------------------*/
3286 /* genCall - generates a call statement                            */
3287 /*-----------------------------------------------------------------*/
3288 static void genCall (iCode *ic)
3289 {
3290   sym_link *ftype;   
3291   int stackParms=0;
3292   int use_wreg=0;
3293   int inwparam=0;
3294   char *fname;
3295   
3296     FENTRY;
3297
3298     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3299     /* if caller saves & we have not saved then */
3300 //    if (!ic->regsSaved)
3301 //      saveRegisters(ic);
3302
3303         /* initialise stackParms for IPUSH pushes */
3304 //      stackParms = psuedoStkPtr;
3305 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3306     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3307     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3308
3309 #if 0
3310     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3311 #endif
3312
3313     /* if send set is not empty the assign */
3314     if (_G.sendSet) {
3315       iCode *sic;
3316       int psuedoStkPtr=-1; 
3317       int firstTimeThruLoop = 1;
3318
3319
3320         /* reverse sendSet if function is not reentrant */
3321         if(!IFFUNC_ISREENT(ftype))
3322           _G.sendSet = reverseSet(_G.sendSet);
3323
3324         /* First figure how many parameters are getting passed */
3325         stackParms = 0;
3326         use_wreg = 0;
3327         
3328         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3329           int size;
3330 //          int offset = 0;
3331
3332             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3333             size = AOP_SIZE(IC_LEFT(sic));
3334
3335             stackParms += size;
3336
3337             /* pass the last byte through WREG */
3338             if(inwparam) {
3339
3340               while (size--) {
3341                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3342                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3343                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3344
3345                 if(!firstTimeThruLoop) {
3346                   /* If this is not the first time we've been through the loop
3347                    * then we need to save the parameter in a temporary
3348                    * register. The last byte of the last parameter is
3349                    * passed in W. */
3350
3351                   pushw();
3352 //                  --psuedoStkPtr;             // sanity check
3353                   use_wreg = 1;
3354                 }
3355                 
3356                 firstTimeThruLoop=0;
3357
3358                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3359
3360 //                offset++;
3361               }
3362             } else {
3363               /* all arguments are passed via stack */
3364               use_wreg = 0;
3365
3366               while (size--) {
3367                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3368                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3369                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3370
3371 //                pushaop(AOP(IC_LEFT(sic)), size);
3372                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3373                                 
3374                 if(!_G.resDirect)
3375                   pushw();
3376               }
3377             }
3378
3379             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3380           }
3381
3382           if(inwparam) {
3383             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3384               pushw();  /* save last parameter to stack if functions has varargs */
3385               use_wreg = 0;
3386             } else
3387               use_wreg = 1;
3388           } else use_wreg = 0;
3389
3390           _G.stackRegSet = _G.sendSet;
3391           _G.sendSet = NULL;
3392     }
3393
3394     /* make the call */
3395     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3396
3397     GpsuedoStkPtr=0;
3398     
3399     /* if we need to assign a result value */
3400     if ((IS_ITEMP(IC_RESULT(ic))
3401           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3402               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3403         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3404
3405       _G.accInUse++;
3406       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3407       _G.accInUse--;
3408
3409       assignResultValue(IC_RESULT(ic), 1);
3410
3411       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3413                 
3414       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3415     }
3416
3417     if(!stackParms && ic->parmBytes) {
3418       stackParms = ic->parmBytes;
3419     }
3420       
3421     stackParms -= use_wreg;
3422     
3423     if(stackParms>0) {
3424       if(stackParms == 1) {
3425         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3426       } else {
3427         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3428         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3429       }
3430       if(STACK_MODEL_LARGE) {
3431         emitSKPNC;
3432         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3433       }
3434     }
3435
3436 #if 0
3437     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3438 #endif
3439
3440     /* adjust the stack for parameters if required */
3441 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3442
3443 #if 0
3444       /* if register bank was saved then pop them */
3445       if (ic->bankSaved)
3446         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3447
3448       /* if we hade saved some registers then unsave them */
3449       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3450         unsaveRegisters (ic);
3451 #endif
3452 }
3453
3454
3455
3456 /*-----------------------------------------------------------------*/
3457 /* genPcall - generates a call by pointer statement                */
3458 /*            new version, created from genCall - HJD              */
3459 /*-----------------------------------------------------------------*/
3460 static void genPcall (iCode *ic)
3461 {
3462   sym_link *fntype;
3463   int stackParms=0;
3464   symbol *retlbl = newiTempLabel(NULL);
3465   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3466   
3467     FENTRY;
3468
3469     fntype = operandType( IC_LEFT(ic) )->next;
3470
3471     /* if send set is not empty the assign */
3472     if (_G.sendSet) {
3473       iCode *sic;
3474       int psuedoStkPtr=-1; 
3475
3476       /* reverse sendSet if function is not reentrant */
3477       if(!IFFUNC_ISREENT(fntype))
3478         _G.sendSet = reverseSet(_G.sendSet);
3479
3480       stackParms = 0;
3481       
3482       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3483         int size;
3484
3485           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3486           size = AOP_SIZE(IC_LEFT(sic));
3487           stackParms += size;
3488
3489           /* all parameters are passed via stack, since WREG is clobbered
3490            * by the calling sequence */
3491           while (size--) {
3492             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3493             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3494             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3495
3496             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3497             pushw();
3498           }
3499
3500           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3501       }
3502
3503       _G.stackRegSet = _G.sendSet;
3504       _G.sendSet = NULL;
3505     }
3506
3507     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3508
3509     // push return address
3510     // push $ on return stack, then replace with retlbl
3511
3512     /* Thanks to Thorsten Klose for pointing out that the following
3513      * snippet should be interrupt safe */
3514     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3515     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3516
3517     pic16_emitpcodeNULLop(POC_PUSH);
3518
3519     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3520     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3521     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3522     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3523     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3524     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3525
3526
3527     /* restore interrupt control register */
3528     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3530
3531     /* make the call by writing the pointer into pc */
3532     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3533     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3534
3535     // note: MOVFF to PCL not allowed
3536     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3537     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3538
3539
3540     /* return address is here: (X) */
3541     pic16_emitpLabelFORCE(retlbl->key);
3542
3543     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3544
3545     GpsuedoStkPtr=0;
3546     /* if we need assign a result value */
3547     if ((IS_ITEMP(IC_RESULT(ic))
3548           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3549               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3550         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3551
3552       _G.accInUse++;
3553       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3554       _G.accInUse--;
3555
3556       assignResultValue(IC_RESULT(ic), 1);
3557
3558       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3559               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3560                 
3561       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3562     }
3563
3564 //    stackParms -= use_wreg;
3565     
3566     if(stackParms>0) {
3567       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3568       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3569       if(STACK_MODEL_LARGE) {
3570         emitSKPNC;
3571         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3572       }
3573     }
3574 }
3575
3576 /*-----------------------------------------------------------------*/
3577 /* resultRemat - result  is rematerializable                       */
3578 /*-----------------------------------------------------------------*/
3579 static int resultRemat (iCode *ic)
3580 {
3581   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3582   if (SKIP_IC(ic) || ic->op == IFX)
3583     return 0;
3584
3585   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3586     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3587     if (sym->remat && !POINTER_SET(ic)) 
3588       return 1;
3589   }
3590
3591   return 0;
3592 }
3593
3594 #if defined(__BORLANDC__) || defined(_MSC_VER)
3595 #define STRCASECMP stricmp
3596 #else
3597 #define STRCASECMP strcasecmp
3598 #endif
3599
3600 #if 0
3601 /*-----------------------------------------------------------------*/
3602 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3603 /*-----------------------------------------------------------------*/
3604 static bool inExcludeList(char *s)
3605 {
3606   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3607     int i =0;
3608     
3609     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3610     if (options.excludeRegs[i] &&
3611     STRCASECMP(options.excludeRegs[i],"none") == 0)
3612         return FALSE ;
3613
3614     for ( i = 0 ; options.excludeRegs[i]; i++) {
3615         if (options.excludeRegs[i] &&
3616         STRCASECMP(s,options.excludeRegs[i]) == 0)
3617             return TRUE;
3618     }
3619     return FALSE ;
3620 }
3621 #endif
3622
3623 /*-----------------------------------------------------------------*/
3624 /* genFunction - generated code for function entry                 */
3625 /*-----------------------------------------------------------------*/
3626 static void genFunction (iCode *ic)
3627 {
3628   symbol *sym;
3629   sym_link *ftype;
3630   
3631     FENTRY;
3632     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3633
3634     pic16_labelOffset += (max_key+4);
3635     max_key=0;
3636     GpsuedoStkPtr=0;
3637     _G.nRegsSaved = 0;
3638         
3639     ftype = operandType(IC_LEFT(ic));
3640     sym = OP_SYMBOL(IC_LEFT(ic));
3641
3642     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3643       /* create an absolute section at the interrupt vector:
3644        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3645       symbol *asym;
3646       char asymname[128];
3647       pBlock *apb;
3648
3649 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3650
3651         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3652           sprintf(asymname, "ivec_%s", sym->name);
3653         else
3654           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3655   
3656         /* when an interrupt is declared as naked, do not emit the special
3657          * wrapper segment at vector address. The user should take care for
3658          * this instead. -- VR */
3659
3660         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3661           asym = newSymbol(asymname, 0);
3662           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3663           pic16_addpBlock( apb );
3664
3665           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3666           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3667           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3668           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3669           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3670                 
3671           /* mark the end of this tiny function */
3672           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3673         } else {
3674           sprintf(asymname, "%s", sym->rname);
3675         }
3676
3677         {
3678           absSym *abSym;
3679
3680             abSym = Safe_calloc(1, sizeof(absSym));
3681             strcpy(abSym->name, asymname);
3682
3683             switch( FUNC_INTNO(sym->type) ) {
3684               case 0: abSym->address = 0x000000; break;
3685               case 1: abSym->address = 0x000008; break;
3686               case 2: abSym->address = 0x000018; break;
3687               
3688               default:
3689 //                fprintf(stderr, "no interrupt number is given\n");
3690                 abSym->address = -1; break;
3691             }
3692
3693             /* relocate interrupt vectors if needed */
3694             if(abSym->address != -1)
3695               abSym->address += pic16_options.ivt_loc;
3696
3697             addSet(&absSymSet, abSym);
3698         }
3699     }
3700
3701     /* create the function header */
3702     pic16_emitcode(";","-----------------------------------------");
3703     pic16_emitcode(";"," function %s",sym->name);
3704     pic16_emitcode(";","-----------------------------------------");
3705
3706     pic16_emitcode("","%s:",sym->rname);
3707     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3708
3709     {
3710       absSym *ab;
3711
3712         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3713           if(!strcmp(ab->name, sym->rname)) {
3714             pic16_pBlockConvert2Absolute(pb);
3715             break;
3716           }
3717         }
3718     }
3719
3720     if(IFFUNC_ISNAKED(ftype)) {
3721       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3722       return;
3723     }
3724         
3725     /* if critical function then turn interrupts off */
3726     if (IFFUNC_ISCRITICAL(ftype)) {
3727       //pic16_emitcode("clr","ea");
3728     }
3729
3730     currFunc = sym;             /* update the currFunc symbol */
3731     _G.fregsUsed = sym->regsUsed;
3732     _G.sregsAlloc = newBitVect(128);
3733     
3734
3735     /* if this is an interrupt service routine then
3736      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3737     if (IFFUNC_ISISR(sym->type)) {
3738         _G.usefastretfie = 1;   /* use shadow registers by default */
3739         
3740         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3741         if(!FUNC_ISSHADOWREGS(sym->type)) {
3742           /* do not save WREG,STATUS,BSR for high priority interrupts
3743            * because they are stored in the hardware shadow registers already */
3744           _G.usefastretfie = 0;
3745           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3746           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3747           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3748         }
3749
3750         /* these should really be optimized somehow, because not all
3751          * interrupt handlers modify them */
3752         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3753         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3754         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3755         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3756         
3757 //        pic16_pBlockConvert2ISR(pb);
3758     }
3759
3760     /* emit code to setup stack frame if user enabled,
3761      * and function is not main() */
3762     
3763 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3764     if(strcmp(sym->name, "main")) {
3765       if(0 
3766         || !options.ommitFramePtr 
3767 //        || sym->regsUsed
3768         || IFFUNC_ARGS(sym->type)
3769         || FUNC_HASSTACKPARM(sym->etype)
3770         ) {
3771         /* setup the stack frame */
3772         if(STACK_MODEL_LARGE)
3773           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3774         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3775
3776         if(STACK_MODEL_LARGE)
3777           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3778         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3779       }
3780     }
3781
3782     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3783           && sym->stack) {
3784
3785       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3786
3787       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3788       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3789       emitSKPC;
3790       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3791     }
3792           
3793     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3794       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3795         _G.useWreg = 0;
3796       else
3797         _G.useWreg = 1;
3798     } else
3799       _G.useWreg = 0;
3800
3801     /* if callee-save to be used for this function
3802      * then save the registers being used in this function */
3803 //    if (IFFUNC_CALLEESAVES(sym->type))
3804     if(strcmp(sym->name, "main")) {
3805       int i;
3806
3807         /* if any registers used */
3808         if (sym->regsUsed) {
3809                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3810
3811           if(!xinst) {
3812             /* save the registers used */
3813             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3814             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3815               if (bitVectBitValue(sym->regsUsed,i)) {
3816 #if 0
3817                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3818 #endif
3819                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3820                 _G.nRegsSaved++;
3821
3822                 if(!pic16_regWithIdx(i)->wasUsed) {
3823                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3824                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3825                   pic16_regWithIdx(i)->wasUsed = 1;
3826                 }
3827               }
3828             }
3829           } else {
3830             
3831             /* xinst */
3832             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3833             for(i=0;i<sym->regsUsed->size;i++) {
3834               if(bitVectBitValue(sym->regsUsed, i)) {
3835                 _G.nRegsSaved++;
3836               }
3837             }
3838                         
3839 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3840           }
3841
3842           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3843
3844         }
3845     }
3846         
3847     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3848 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3849 }
3850
3851 /*-----------------------------------------------------------------*/
3852 /* genEndFunction - generates epilogue for functions               */
3853 /*-----------------------------------------------------------------*/
3854 static void genEndFunction (iCode *ic)
3855 {
3856   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3857
3858     FENTRY;
3859
3860     if(IFFUNC_ISNAKED(sym->type)) {
3861       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3862       return;
3863     }
3864
3865     _G.stack_lat = 0;
3866
3867     /* add code for ISCRITICAL */
3868     if(IFFUNC_ISCRITICAL(sym->type)) {
3869       /* if critical function, turn on interrupts */
3870       
3871       /* TODO: add code here -- VR */
3872     }
3873     
3874 //    sym->regsUsed = _G.fregsUsed;
3875     
3876     /* now we need to restore the registers */
3877     /* if any registers used */
3878
3879     /* first restore registers that might be used for stack access */
3880     if(_G.sregsAllocSet) {
3881     regs *sr;
3882     
3883       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3884       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3885         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3886       }
3887     }
3888
3889     if (strcmp(sym->name, "main") && sym->regsUsed) {
3890       int i;
3891
3892         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3893         /* restore registers used */
3894         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3895         for ( i = sym->regsUsed->size; i >= 0; i--) {
3896           if (bitVectBitValue(sym->regsUsed,i)) {
3897             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3898             _G.nRegsSaved--;
3899           }
3900         }
3901         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3902     }
3903
3904       
3905
3906     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3907           && sym->stack) {
3908       if (sym->stack == 1) {
3909         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3910         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3911       } else {
3912         // we have to add more than one...
3913         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3914         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3915         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3916         emitSKPNC;
3917         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3918         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3919         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3920       }
3921     }
3922
3923     if(strcmp(sym->name, "main")) {
3924       if(0
3925         || !options.ommitFramePtr
3926 //        || sym->regsUsed
3927         || IFFUNC_ARGS(sym->type)
3928         || FUNC_HASSTACKPARM(sym->etype)
3929         ) {
3930         /* restore stack frame */
3931         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3932         if(STACK_MODEL_LARGE)
3933           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3934       }
3935     }
3936
3937     _G.useWreg = 0;
3938
3939     if (IFFUNC_ISISR(sym->type)) {
3940       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3941       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3942       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3943       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3944
3945       if(!FUNC_ISSHADOWREGS(sym->type)) {
3946         /* do not restore interrupt vector for WREG,STATUS,BSR
3947          * for high priority interrupt, see genFunction */
3948         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3949         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3950         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3951       }
3952 //      _G.interruptvector = 0;         /* sanity check */
3953
3954
3955       /* if debug then send end of function */
3956 /*      if (options.debug && currFunc)  */
3957       if (currFunc) {
3958         debugFile->writeEndFunction (currFunc, ic, 1);
3959       }
3960         
3961       if(_G.usefastretfie)
3962         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3963       else
3964         pic16_emitpcodeNULLop(POC_RETFIE);
3965
3966       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3967       
3968       _G.usefastretfie = 0;
3969       return;
3970     }
3971
3972     if (IFFUNC_ISCRITICAL(sym->type)) {
3973       pic16_emitcode("setb","ea");
3974     }
3975
3976     /* if debug then send end of function */
3977     if (currFunc) {
3978       debugFile->writeEndFunction (currFunc, ic, 1);
3979     }
3980
3981     /* insert code to restore stack frame, if user enabled it
3982      * and function is not main() */
3983          
3984
3985     pic16_emitpcodeNULLop(POC_RETURN);
3986
3987     /* Mark the end of a function */
3988     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3989 }
3990
3991
3992 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3993 {
3994   unsigned long lit=1;
3995   operand *op;
3996
3997     op = IC_LEFT(ic);
3998   
3999     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4000     if(AOP_TYPE(op) == AOP_LIT) {
4001       if(!IS_FLOAT(operandType( op ))) {
4002         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4003       } else {
4004         union {
4005           unsigned long lit_int;
4006           float lit_float;
4007         } info;
4008         
4009         /* take care if literal is a float */
4010         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4011         lit = info.lit_int;
4012       }
4013     }
4014
4015     if (AOP_TYPE(op) == AOP_LIT) {
4016       /* FIXME: broken for
4017        *   char __at(0x456) foo;
4018        *   return &foo;
4019        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4020       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4021     } else if (AOP_TYPE(op) == AOP_PCODE
4022                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4023       /* char *s= "aaa"; return s; */
4024       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4025        *      that the generic pointer is interpreted correctly
4026        *      as referring to __code space, but this is fragile! */
4027       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4028       /* XXX: should check that dest != WREG */
4029       pic16_emitpcode(POC_MOVWF, dest);
4030     } else {
4031       if(dest->type == PO_WREG && (offset == 0)) {
4032         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4033         return;
4034       }
4035       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4036     }
4037 }
4038
4039 /*-----------------------------------------------------------------*/
4040 /* genRet - generate code for return statement                     */
4041 /*-----------------------------------------------------------------*/
4042 static void genRet (iCode *ic)
4043 {
4044   int size;
4045   operand *left;
4046
4047     FENTRY;
4048         /* if we have no return value then
4049          * just generate the "ret" */
4050         
4051         if (!IC_LEFT(ic)) 
4052                 goto jumpret;       
4053     
4054         /* we have something to return then
4055          * move the return value into place */
4056         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4057         size = AOP_SIZE(IC_LEFT(ic));
4058
4059         if(size <= 4) {
4060           if(size>3)
4061             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4062           
4063           if(size>2)
4064             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4065
4066           if(size>1)
4067             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4068           
4069           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4070
4071         } else {
4072                 /* >32-bits, setup stack and FSR0 */
4073                 while (size--) {
4074 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4075 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4076
4077                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4078
4079 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4080                         GpsuedoStkPtr++;
4081                 }
4082                         
4083                 /* setup FSR0 */
4084                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4085                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4086
4087                 if(STACK_MODEL_LARGE) {
4088                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4089                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4090                 } else {
4091                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4092                 }
4093         }
4094                                 
4095 #if 0
4096         /* old code, left here for reference -- VR */    
4097         while (size--) {
4098           char *l ;
4099
4100                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4101                         /* #NOCHANGE */
4102                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4103                         pic16_emitpcomment("push %s",l);
4104                         pushed++;
4105                 } else {
4106                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4107                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4108                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4109                         
4110                         if (strcmp(fReturn[offset],l)) {
4111                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4112                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4113                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4114                                 } else {
4115                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4116                                 }
4117                                 
4118                                 if(size) {
4119                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4120                                 }
4121                                 offset++;
4122                         }
4123                 }
4124         }    
4125
4126         if (pushed) {
4127                 while(pushed) {
4128                         pushed--;
4129                         if (strcmp(fReturn[pushed],"a"))
4130                                 pic16_emitcode("pop",fReturn[pushed]);
4131                         else
4132                                 pic16_emitcode("pop","acc");
4133                 }
4134         }
4135 #endif
4136
4137
4138         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4139     
4140 jumpret:
4141         /* generate a jump to the return label
4142          * if the next is not the return statement */
4143         if (!(ic->next && ic->next->op == LABEL
4144                 && IC_LABEL(ic->next) == returnLabel)) {
4145         
4146                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4147                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4148         }
4149 }
4150
4151 /*-----------------------------------------------------------------*/
4152 /* genLabel - generates a label                                    */
4153 /*-----------------------------------------------------------------*/
4154 static void genLabel (iCode *ic)
4155 {
4156   FENTRY;
4157
4158   /* special case never generate */
4159   if (IC_LABEL(ic) == entryLabel)
4160     return ;
4161
4162   pic16_emitpLabel(IC_LABEL(ic)->key);
4163 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4164 }
4165
4166 /*-----------------------------------------------------------------*/
4167 /* genGoto - generates a goto                                      */
4168 /*-----------------------------------------------------------------*/
4169 //tsd
4170 static void genGoto (iCode *ic)
4171 {
4172   FENTRY;
4173   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4174 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4175 }
4176
4177
4178 /*-----------------------------------------------------------------*/
4179 /* genMultbits :- multiplication of bits                           */
4180 /*-----------------------------------------------------------------*/
4181 static void genMultbits (operand *left, 
4182                          operand *right, 
4183                          operand *result)
4184 {
4185   FENTRY;
4186
4187   if(!pic16_sameRegs(AOP(result),AOP(right)))
4188     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4189
4190   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4191   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4192   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4193
4194 }
4195
4196
4197 /*-----------------------------------------------------------------*/
4198 /* genMultOneByte : 8 bit multiplication & division                */
4199 /*-----------------------------------------------------------------*/
4200 static void genMultOneByte (operand *left,
4201                             operand *right,
4202                             operand *result)
4203 {
4204
4205   FENTRY;
4206   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4207   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4208
4209   /* (if two literals, the value is computed before) */
4210   /* if one literal, literal on the right */
4211   if (AOP_TYPE(left) == AOP_LIT){
4212     operand *t = right;
4213     right = left;
4214     left = t;
4215   }
4216
4217         /* size is already checked in genMult == 1 */
4218 //      size = AOP_SIZE(result);
4219
4220         if (AOP_TYPE(right) == AOP_LIT){
4221                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4222                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4223                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4224                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4225         } else {
4226                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4227                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4228                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4229                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4230         }
4231         
4232         pic16_genMult8X8_8 (left, right,result);
4233 }
4234
4235 /*-----------------------------------------------------------------*/
4236 /* genMultOneWord : 16 bit multiplication                          */
4237 /*-----------------------------------------------------------------*/
4238 static void genMultOneWord (operand *left,
4239                             operand *right,
4240                             operand *result)
4241 {
4242   FENTRY;
4243   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4244   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4245
4246   /* (if two literals, the value is computed before)
4247    * if one literal, literal on the right */
4248   if (AOP_TYPE(left) == AOP_LIT){
4249     operand *t = right;
4250     right = left;
4251     left = t;
4252   }
4253
4254   /* size is checked already == 2 */
4255 //  size = AOP_SIZE(result);
4256
4257   if (AOP_TYPE(right) == AOP_LIT) {
4258     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4259       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4260       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4261       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4262   } else {
4263     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4264       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4265       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4266       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4267   }
4268         
4269   pic16_genMult16X16_16(left, right,result);
4270 }
4271
4272 /*-----------------------------------------------------------------*/
4273 /* genMultOneLong : 32 bit multiplication                          */
4274 /*-----------------------------------------------------------------*/
4275 static void genMultOneLong (operand *left,
4276                             operand *right,
4277                             operand *result)
4278 {
4279   FENTRY;
4280   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4281   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4282
4283   /* (if two literals, the value is computed before)
4284    * if one literal, literal on the right */
4285   if (AOP_TYPE(left) == AOP_LIT){
4286     operand *t = right;
4287     right = left;
4288     left = t;
4289   }
4290
4291   /* size is checked already == 4 */
4292 //  size = AOP_SIZE(result);
4293
4294   if (AOP_TYPE(right) == AOP_LIT) {
4295     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4296         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4297         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4298         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4299   } else {
4300     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4301         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4302         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4303         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4304   }
4305         
4306   pic16_genMult32X32_32(left, right,result);
4307 }
4308
4309
4310
4311 /*-----------------------------------------------------------------*/
4312 /* genMult - generates code for multiplication                     */
4313 /*-----------------------------------------------------------------*/
4314 static void genMult (iCode *ic)
4315 {
4316   operand *left = IC_LEFT(ic);
4317   operand *right = IC_RIGHT(ic);
4318   operand *result= IC_RESULT(ic);   
4319
4320     FENTRY;
4321         /* assign the amsops */
4322         pic16_aopOp (left,ic,FALSE);
4323         pic16_aopOp (right,ic,FALSE);
4324         pic16_aopOp (result,ic,TRUE);
4325
4326         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4327
4328         /* special cases first *
4329         * both are bits */
4330         if (AOP_TYPE(left) == AOP_CRY
4331                 && AOP_TYPE(right)== AOP_CRY) {
4332                 genMultbits(left,right,result);
4333           goto release ;
4334         }
4335
4336         /* if both are of size == 1 */
4337         if(AOP_SIZE(left) == 1
4338                 && AOP_SIZE(right) == 1) {
4339                 genMultOneByte(left,right,result);
4340           goto release ;
4341         }
4342
4343         /* if both are of size == 2 */
4344         if(AOP_SIZE(left) == 2
4345                 && AOP_SIZE(right) == 2) {
4346                 genMultOneWord(left, right, result);
4347           goto release;
4348         }
4349         
4350         /* if both are of size == 4 */
4351         if(AOP_SIZE(left) == 4
4352                 && AOP_SIZE(right) == 4) {
4353                 genMultOneLong(left, right, result);
4354           goto release;
4355         }
4356         
4357         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4358
4359
4360         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4361         /* should have been converted to function call */
4362         assert(0) ;
4363
4364 release :
4365         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4366         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4367         pic16_freeAsmop(result,NULL,ic,TRUE); 
4368 }
4369
4370 /*-----------------------------------------------------------------*/
4371 /* genDivbits :- division of bits                                  */
4372 /*-----------------------------------------------------------------*/
4373 static void genDivbits (operand *left, 
4374                         operand *right, 
4375                         operand *result)
4376 {
4377   char *l;
4378
4379     FENTRY;
4380     /* the result must be bit */    
4381     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4382     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4383
4384     MOVA(l);    
4385
4386     pic16_emitcode("div","ab");
4387     pic16_emitcode("rrc","a");
4388     pic16_aopPut(AOP(result),"c",0);
4389 }
4390
4391 /*-----------------------------------------------------------------*/
4392 /* genDivOneByte : 8 bit division                                  */
4393 /*-----------------------------------------------------------------*/
4394 static void genDivOneByte (operand *left,
4395                            operand *right,
4396                            operand *result)
4397 {
4398   sym_link *opetype = operandType(result);
4399   char *l ;
4400   symbol *lbl ;
4401   int size,offset;
4402
4403         /* result = divident / divisor
4404          * - divident may be a register or a literal,
4405          * - divisor may be a register or a literal,
4406          * so there are 3 cases (literal / literal is optimized
4407          * by the front-end) to handle.
4408          * In addition we must handle signed and unsigned, which
4409          * result in 6 final different cases -- VR */
4410
4411     FENTRY;
4412     
4413     size = AOP_SIZE(result) - 1;
4414     offset = 1;
4415     /* signed or unsigned */
4416     if (SPEC_USIGN(opetype)) {
4417       pCodeOp *pct1,    /* count */
4418                 *pct2,  /* reste */
4419                 *pct3;  /* temp */
4420       symbol *label1, *label2, *label3;;
4421
4422
4423         /* unsigned is easy */
4424
4425         pct1 = pic16_popGetTempReg(1);
4426         pct2 = pic16_popGetTempReg(1);
4427         pct3 = pic16_popGetTempReg(1);
4428         
4429         label1 = newiTempLabel(NULL);
4430         label2 = newiTempLabel(NULL);
4431         label3 = newiTempLabel(NULL);
4432
4433         /* the following algorithm is extracted from divuint.c */
4434
4435         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4436         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4437         
4438         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4439
4440         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4441         
4442         pic16_emitpLabel(label1->key);
4443         
4444         emitCLRC;
4445         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4446
4447
4448         emitCLRC;
4449         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4450         
4451
4452         emitSKPNC;
4453         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4454         
4455         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4456         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4457         
4458         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4459         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4460         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4461         
4462         pic16_emitpLabel( label3->key );
4463         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4464         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4465         
4466         
4467
4468         pic16_emitpLabel(label2->key);
4469         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4470         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4471         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4472         
4473         /* result is in wreg */
4474         if(AOP_TYPE(result) != AOP_ACC)
4475                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4476
4477         pic16_popReleaseTempReg( pct3, 1);
4478         pic16_popReleaseTempReg( pct2, 1);
4479         pic16_popReleaseTempReg( pct1, 1);
4480
4481         return ;
4482     }
4483
4484     /* signed is a little bit more difficult */
4485
4486     /* save the signs of the operands */
4487     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4488     MOVA(l);    
4489     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4490     pic16_emitcode("push","acc"); /* save it on the stack */
4491
4492     /* now sign adjust for both left & right */
4493     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4494     MOVA(l);       
4495     lbl = newiTempLabel(NULL);
4496     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4497     pic16_emitcode("cpl","a");   
4498     pic16_emitcode("inc","a");
4499     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4500     pic16_emitcode("mov","b,a");
4501
4502     /* sign adjust left side */
4503     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4504     MOVA(l);
4505
4506     lbl = newiTempLabel(NULL);
4507     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4508     pic16_emitcode("cpl","a");
4509     pic16_emitcode("inc","a");
4510     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4511
4512     /* now the division */
4513     pic16_emitcode("div","ab");
4514     /* we are interested in the lower order
4515     only */
4516     pic16_emitcode("mov","b,a");
4517     lbl = newiTempLabel(NULL);
4518     pic16_emitcode("pop","acc");   
4519     /* if there was an over flow we don't 
4520     adjust the sign of the result */
4521     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4522     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4523     CLRC;
4524     pic16_emitcode("clr","a");
4525     pic16_emitcode("subb","a,b");
4526     pic16_emitcode("mov","b,a");
4527     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4528
4529     /* now we are done */
4530     pic16_aopPut(AOP(result),"b",0);
4531     if(size > 0){
4532         pic16_emitcode("mov","c,b.7");
4533         pic16_emitcode("subb","a,acc");   
4534     }
4535     while (size--)
4536         pic16_aopPut(AOP(result),"a",offset++);
4537
4538 }
4539
4540 /*-----------------------------------------------------------------*/
4541 /* genDiv - generates code for division                            */
4542 /*-----------------------------------------------------------------*/
4543 static void genDiv (iCode *ic)
4544 {
4545     operand *left = IC_LEFT(ic);
4546     operand *right = IC_RIGHT(ic);
4547     operand *result= IC_RESULT(ic);   
4548
4549
4550         /* Division is a very lengthy algorithm, so it is better
4551          * to call support routines than inlining algorithm.
4552          * Division functions written here just in case someone
4553          * wants to inline and not use the support libraries -- VR */
4554
4555     FENTRY;
4556     
4557     /* assign the amsops */
4558     pic16_aopOp (left,ic,FALSE);
4559     pic16_aopOp (right,ic,FALSE);
4560     pic16_aopOp (result,ic,TRUE);
4561
4562     /* special cases first */
4563     /* both are bits */
4564     if (AOP_TYPE(left) == AOP_CRY &&
4565         AOP_TYPE(right)== AOP_CRY) {
4566         genDivbits(left,right,result);
4567         goto release ;
4568     }
4569
4570     /* if both are of size == 1 */
4571     if (AOP_SIZE(left) == 1 &&
4572         AOP_SIZE(right) == 1 ) {
4573         genDivOneByte(left,right,result);
4574         goto release ;
4575     }
4576
4577     /* should have been converted to function call */
4578     assert(0);
4579 release :
4580     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4581     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4582     pic16_freeAsmop(result,NULL,ic,TRUE); 
4583 }
4584
4585 /*-----------------------------------------------------------------*/
4586 /* genModbits :- modulus of bits                                   */
4587 /*-----------------------------------------------------------------*/
4588 static void genModbits (operand *left, 
4589                         operand *right, 
4590                         operand *result)
4591 {
4592   char *l;
4593
4594     FENTRY;  
4595     
4596     werror(W_POSSBUG2, __FILE__, __LINE__);
4597     /* the result must be bit */    
4598     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4599     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4600
4601     MOVA(l);       
4602
4603     pic16_emitcode("div","ab");
4604     pic16_emitcode("mov","a,b");
4605     pic16_emitcode("rrc","a");
4606     pic16_aopPut(AOP(result),"c",0);
4607 }
4608
4609 /*-----------------------------------------------------------------*/
4610 /* genModOneByte : 8 bit modulus                                   */
4611 /*-----------------------------------------------------------------*/
4612 static void genModOneByte (operand *left,
4613                            operand *right,
4614                            operand *result)
4615 {
4616   sym_link *opetype = operandType(result);
4617   char *l ;
4618   symbol *lbl ;
4619
4620     FENTRY;
4621     werror(W_POSSBUG2, __FILE__, __LINE__);
4622
4623     /* signed or unsigned */
4624     if (SPEC_USIGN(opetype)) {
4625         /* unsigned is easy */
4626         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4627         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4628         MOVA(l);    
4629         pic16_emitcode("div","ab");
4630         pic16_aopPut(AOP(result),"b",0);
4631         return ;
4632     }
4633
4634     /* signed is a little bit more difficult */
4635
4636     /* save the signs of the operands */
4637     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4638     MOVA(l);
4639
4640     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4641     pic16_emitcode("push","acc"); /* save it on the stack */
4642
4643     /* now sign adjust for both left & right */
4644     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4645     MOVA(l);
4646
4647     lbl = newiTempLabel(NULL);
4648     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4649     pic16_emitcode("cpl","a");   
4650     pic16_emitcode("inc","a");
4651     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4652     pic16_emitcode("mov","b,a"); 
4653
4654     /* sign adjust left side */
4655     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4656     MOVA(l);
4657
4658     lbl = newiTempLabel(NULL);
4659     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4660     pic16_emitcode("cpl","a");   
4661     pic16_emitcode("inc","a");
4662     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4663
4664     /* now the multiplication */
4665     pic16_emitcode("div","ab");
4666     /* we are interested in the lower order
4667     only */
4668     lbl = newiTempLabel(NULL);
4669     pic16_emitcode("pop","acc");   
4670     /* if there was an over flow we don't 
4671     adjust the sign of the result */
4672     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4673     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4674     CLRC ;
4675     pic16_emitcode("clr","a");
4676     pic16_emitcode("subb","a,b");
4677     pic16_emitcode("mov","b,a");
4678     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4679
4680     /* now we are done */
4681     pic16_aopPut(AOP(result),"b",0);
4682
4683 }
4684
4685 /*-----------------------------------------------------------------*/
4686 /* genMod - generates code for division                            */
4687 /*-----------------------------------------------------------------*/
4688 static void genMod (iCode *ic)
4689 {
4690   operand *left = IC_LEFT(ic);
4691   operand *right = IC_RIGHT(ic);
4692   operand *result= IC_RESULT(ic);  
4693
4694     FENTRY;
4695     
4696     /* assign the amsops */
4697     pic16_aopOp (left,ic,FALSE);
4698     pic16_aopOp (right,ic,FALSE);
4699     pic16_aopOp (result,ic,TRUE);
4700
4701     /* special cases first */
4702     /* both are bits */
4703     if (AOP_TYPE(left) == AOP_CRY &&
4704         AOP_TYPE(right)== AOP_CRY) {
4705         genModbits(left,right,result);
4706         goto release ;
4707     }
4708
4709     /* if both are of size == 1 */
4710     if (AOP_SIZE(left) == 1 &&
4711         AOP_SIZE(right) == 1 ) {
4712         genModOneByte(left,right,result);
4713         goto release ;
4714     }
4715
4716     /* should have been converted to function call */
4717     assert(0);
4718
4719 release :
4720     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4721     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4722     pic16_freeAsmop(result,NULL,ic,TRUE); 
4723 }
4724
4725 /*-----------------------------------------------------------------*/
4726 /* genIfxJump :- will create a jump depending on the ifx           */
4727 /*-----------------------------------------------------------------*/
4728 /*
4729   note: May need to add parameter to indicate when a variable is in bit space.
4730 */
4731 static void genIfxJump (iCode *ic, char *jval)
4732 {
4733   FENTRY;
4734   
4735     /* if true label then we jump if condition
4736     supplied is true */
4737     if ( IC_TRUE(ic) ) {
4738
4739         if(strcmp(jval,"a") == 0)
4740           emitSKPZ;
4741         else if (strcmp(jval,"c") == 0)
4742           emitSKPNC;
4743         else {
4744           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4745           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4746         }
4747
4748         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4749         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4750
4751     }
4752     else {
4753         /* false label is present */
4754         if(strcmp(jval,"a") == 0)
4755           emitSKPNZ;
4756         else if (strcmp(jval,"c") == 0)
4757           emitSKPC;
4758         else {
4759           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4760           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4761         }
4762
4763         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4764         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4765
4766     }
4767
4768
4769     /* mark the icode as generated */
4770     ic->generated = 1;
4771 }
4772
4773 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4774 {
4775   FENTRY;
4776   
4777     /* if true label then we jump if condition
4778     supplied is true */
4779     if ( IC_TRUE(ic) ) {
4780       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4781       pic16_emitpcode(POC_BTFSC, jop);
4782
4783       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4784       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4785
4786     } else {
4787       /* false label is present */
4788       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4789       pic16_emitpcode(POC_BTFSS, jop);
4790           
4791       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4792       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4793     }
4794
4795
4796     /* mark the icode as generated */
4797     ic->generated = 1;
4798 }
4799
4800 #if 0
4801 // not needed ATM
4802
4803 /*-----------------------------------------------------------------*/
4804 /* genSkip                                                         */
4805 /*-----------------------------------------------------------------*/
4806 static void genSkip(iCode *ifx,int status_bit)
4807 {
4808   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4809   if(!ifx)
4810     return;
4811
4812   if ( IC_TRUE(ifx) ) {
4813     switch(status_bit) {
4814     case 'z':
4815       emitSKPNZ;
4816       break;
4817
4818     case 'c':
4819       emitSKPNC;
4820       break;
4821
4822     case 'd':
4823       emitSKPDC;
4824       break;
4825
4826     }
4827
4828     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4829     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4830
4831   } else {
4832
4833     switch(status_bit) {
4834
4835     case 'z':
4836       emitSKPZ;
4837       break;
4838
4839     case 'c':
4840       emitSKPC;
4841       break;
4842
4843     case 'd':
4844       emitSKPDC;
4845       break;
4846     }
4847     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4848     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4849
4850   }
4851
4852 }
4853 #endif
4854
4855 /*-----------------------------------------------------------------*/
4856 /* genSkipc                                                        */
4857 /*-----------------------------------------------------------------*/
4858 static void genSkipc(resolvedIfx *rifx)
4859 {
4860   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4861   
4862   if(!rifx)
4863     return;
4864
4865   if(rifx->condition)
4866     emitSKPNC;
4867   else
4868     emitSKPC;
4869
4870   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4871   rifx->generated = 1;
4872 }
4873
4874 #if !(USE_SIMPLE_GENCMP)
4875 /*-----------------------------------------------------------------*/
4876 /* genSkipz2                                                       */
4877 /*-----------------------------------------------------------------*/
4878 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4879 {
4880   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4881   
4882   if(!rifx)
4883     return;
4884
4885   if( (rifx->condition ^ invert_condition) & 1)
4886     emitSKPZ;
4887   else
4888     emitSKPNZ;
4889
4890   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4891   rifx->generated = 1;
4892 }
4893 #endif
4894
4895 #if 0
4896 /*-----------------------------------------------------------------*/
4897 /* genSkipz                                                        */
4898 /*-----------------------------------------------------------------*/
4899 static void genSkipz(iCode *ifx, int condition)
4900 {
4901   if(!ifx)
4902     return;
4903
4904   if(condition)
4905     emitSKPNZ;
4906   else
4907     emitSKPZ;
4908
4909   if ( IC_TRUE(ifx) )
4910     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4911   else
4912     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4913
4914   if ( IC_TRUE(ifx) )
4915     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4916   else
4917     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4918
4919 }
4920 #endif
4921
4922 #if !(USE_SIMPLE_GENCMP)
4923 /*-----------------------------------------------------------------*/
4924 /* genSkipCond                                                     */
4925 /*-----------------------------------------------------------------*/
4926 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4927 {
4928   if(!rifx)
4929     return;
4930
4931   if(rifx->condition)
4932     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4933   else
4934     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4935
4936
4937   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4938   rifx->generated = 1;
4939 }
4940 #endif
4941
4942 #if 0
4943 /*-----------------------------------------------------------------*/
4944 /* genChkZeroes :- greater or less than comparison                 */
4945 /*     For each byte in a literal that is zero, inclusive or the   */
4946 /*     the corresponding byte in the operand with W                */
4947 /*     returns true if any of the bytes are zero                   */
4948 /*-----------------------------------------------------------------*/
4949 static int genChkZeroes(operand *op, int lit,  int size)
4950 {
4951
4952   int i;
4953   int flag =1;
4954
4955   while(size--) {
4956     i = (lit >> (size*8)) & 0xff;
4957
4958     if(i==0) {
4959       if(flag) 
4960         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4961       else
4962         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4963       flag = 0;
4964     }
4965   }
4966
4967   return (flag==0);
4968 }
4969 #endif
4970
4971
4972 /*-----------------------------------------------------------------*/
4973 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4974 /*                  aop (if it's NOT a literal) or from lit (if    */
4975 /*                  aop is a literal)                              */
4976 /*-----------------------------------------------------------------*/
4977 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4978   if (aop->type == AOP_LIT) {
4979     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4980   } else {
4981     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4982   }
4983 }
4984
4985 /*-----------------------------------------------------------------*/
4986 /* genCmp :- greater or less than comparison                       */
4987 /*-----------------------------------------------------------------*/
4988
4989 #if USE_SIMPLE_GENCMP           /* { */
4990
4991 /* genCmp performs a left < right comparison, stores
4992  * the outcome in result (if != NULL) and generates
4993  * control flow code for the ifx (if != NULL).
4994  *
4995  * This version leaves in sequences like
4996  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4997  * which should be optmized by the peephole
4998  * optimizer - RN 2005-01-01 */
4999 static void genCmp (operand *left,operand *right,
5000                     operand *result, iCode *ifx, int sign)
5001 {
5002   resolvedIfx rIfx;
5003   int size;
5004   int offs;
5005   symbol *templbl;
5006   operand *dummy;
5007   unsigned long lit;
5008   unsigned long mask;
5009   int performedLt;
5010
5011   FENTRY;
5012   
5013   assert (left && right);
5014   assert (AOP_SIZE(left) == AOP_SIZE(right));
5015
5016   size = AOP_SIZE(right) - 1;
5017   mask = (0x100UL << (size*8)) - 1;
5018   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5019   performedLt = 1;
5020   templbl = NULL;
5021   lit = 0;
5022   
5023   resolveIfx (&rIfx, ifx);
5024
5025   /* handle for special cases */
5026   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5027       return;
5028
5029   /**********************************************************************
5030    * handle bits - bit compares are promoted to int compares seemingly! *
5031    **********************************************************************/
5032 #if 0
5033   // THIS IS COMPLETELY UNTESTED!
5034   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5035     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5036     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5037     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5038
5039     emitSETC;
5040     // 1 < {0,1} is false --> clear C by skipping the next instruction
5041     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5042     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5043     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5044     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5045     emitCLRC; // only skipped for left=0 && right=1
5046
5047     goto correct_result_in_carry;
5048   } // if
5049 #endif
5050
5051   /*************************************************
5052    * make sure that left is register (or the like) *
5053    *************************************************/
5054   if (!isAOP_REGlike(left)) {
5055     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5056     assert (isAOP_LIT(left));
5057     assert (isAOP_REGlike(right));
5058     // swap left and right
5059     // left < right <==> right > left <==> (right >= left + 1)
5060     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5061
5062     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5063       // MAXVALUE < right? always false
5064       if (performedLt) emitCLRC; else emitSETC;
5065       goto correct_result_in_carry;
5066     } // if
5067
5068     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5069     // that's why we handled it above.
5070     lit++;
5071
5072     dummy = left;
5073     left = right;
5074     right = dummy;
5075
5076     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5077   } else if (isAOP_LIT(right)) {
5078     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5079   } // if
5080
5081   assert (isAOP_REGlike(left)); // left must be register or the like
5082   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5083
5084   /*************************************************
5085    * special cases go here                         *
5086    *************************************************/
5087
5088   if (isAOP_LIT(right)) {
5089     if (!sign) {
5090       // unsigned comparison to a literal
5091       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5092       if (lit == 0) {
5093         // unsigned left < 0? always false
5094         if (performedLt) emitCLRC; else emitSETC;
5095         goto correct_result_in_carry;
5096       }
5097     } else {
5098       // signed comparison to a literal
5099       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5100       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5101         // signed left < 0x80000000? always false
5102         if (performedLt) emitCLRC; else emitSETC;
5103         goto correct_result_in_carry;
5104       } else if (lit == 0) {
5105         // compare left < 0; set CARRY if SIGNBIT(left) is set
5106         if (performedLt) emitSETC; else emitCLRC;
5107         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5108         if (performedLt) emitCLRC; else emitSETC;
5109         goto correct_result_in_carry;
5110       }
5111     } // if (!sign)
5112   } // right is literal
5113
5114   /*************************************************
5115    * perform a general case comparison             *
5116    * make sure we get CARRY==1 <==> left >= right  *
5117    *************************************************/
5118   // compare most significant bytes
5119   //DEBUGpc ("comparing bytes at offset %d", size);
5120   if (!sign) {
5121     // unsigned comparison
5122     mov2w_regOrLit (AOP(right), lit, size);
5123     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5124   } else {
5125     // signed comparison
5126     // (add 2^n to both operands then perform an unsigned comparison)
5127     if (isAOP_LIT(right)) {
5128       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5129       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5130
5131       if (litbyte == 0x80) {
5132         // left >= 0x80 -- always true, but more bytes to come
5133         pic16_mov2w (AOP(left), size);
5134         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5135         emitSETC;
5136       } else {
5137         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5138         pic16_mov2w (AOP(left), size);
5139         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5140         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5141       } // if
5142     } else {
5143       /* using PRODL as a temporary register here */
5144       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5145       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5146       pic16_mov2w (AOP(left), size);
5147       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5148       pic16_emitpcode (POC_MOVWF, pctemp);
5149       pic16_mov2w (AOP(right), size);
5150       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5151       pic16_emitpcode (POC_SUBFW, pctemp);
5152       //pic16_popReleaseTempReg(pctemp, 1);
5153     }
5154   } // if (!sign)
5155
5156   // compare remaining bytes (treat as unsigned case from above)
5157   templbl = newiTempLabel ( NULL );
5158   offs = size;
5159   while (offs--) {
5160     //DEBUGpc ("comparing bytes at offset %d", offs);
5161     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5162     mov2w_regOrLit (AOP(right), lit, offs);
5163     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5164   } // while (offs)
5165   pic16_emitpLabel (templbl->key);
5166   goto result_in_carry;
5167
5168 result_in_carry:
5169   
5170   /****************************************************
5171    * now CARRY contains the result of the comparison: *
5172    * SUBWF sets CARRY iff                             *
5173    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5174    * (F=left, W=right)                                *
5175    ****************************************************/
5176
5177   if (performedLt) {
5178     if (result && AOP_TYPE(result) != AOP_CRY) {
5179       // value will be stored
5180       emitTOGC;
5181     } else {
5182       // value wil only be used in the following genSkipc()
5183       rIfx.condition ^= 1;
5184     }
5185   } // if
5186
5187 correct_result_in_carry:
5188
5189   // assign result to variable (if neccessary)
5190   if (result && AOP_TYPE(result) != AOP_CRY) {
5191     //DEBUGpc ("assign result");
5192     size = AOP_SIZE(result);
5193     while (size--) {
5194       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5195     } // while
5196     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5197   } // if (result)
5198
5199   // perform conditional jump
5200   if (ifx) {
5201     //DEBUGpc ("generate control flow");
5202     genSkipc (&rIfx);
5203     ifx->generated = 1;
5204   } // if
5205 }
5206
5207 #elif 1         /* } */
5208                 /* { */
5209       /* original code */
5210 static void genCmp (operand *left,operand *right,
5211                     operand *result, iCode *ifx, int sign)
5212 {
5213   int size; //, offset = 0 ;
5214   unsigned long lit = 0L,i = 0;
5215   resolvedIfx rFalseIfx;
5216   //  resolvedIfx rTrueIfx;
5217   symbol *truelbl;
5218   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5219 /*
5220   if(ifx) {
5221     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5222     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5223   }
5224 */
5225
5226   FENTRY;
5227   
5228   resolveIfx(&rFalseIfx,ifx);
5229   truelbl  = newiTempLabel(NULL);
5230   size = max(AOP_SIZE(left),AOP_SIZE(right));
5231
5232   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5233
5234 #define _swapp
5235
5236   /* if literal is on the right then swap with left */
5237   if ((AOP_TYPE(right) == AOP_LIT)) {
5238     operand *tmp = right ;
5239     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5240     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5241 #ifdef _swapp
5242
5243     lit = (lit - 1) & mask;
5244     right = left;
5245     left = tmp;
5246     rFalseIfx.condition ^= 1;
5247 #endif
5248
5249   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5250     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5251   }
5252
5253
5254   //if(IC_TRUE(ifx) == NULL)
5255   /* if left & right are bit variables */
5256   if (AOP_TYPE(left) == AOP_CRY &&
5257       AOP_TYPE(right) == AOP_CRY ) {
5258     assert (0 && "bit variables used in genCmp");
5259     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5260     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5261   } else {
5262     /* subtract right from left if at the
5263        end the carry flag is set then we know that
5264        left is greater than right */
5265
5266     symbol *lbl  = newiTempLabel(NULL);
5267
5268 #if 0
5269         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5270                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5271 #endif
5272
5273 #ifndef _swapp
5274     if(AOP_TYPE(right) == AOP_LIT) {
5275
5276       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5277
5278       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5279
5280       /* special cases */
5281
5282       if(lit == 0) {
5283
5284         if(sign != 0) 
5285           genSkipCond(&rFalseIfx,left,size-1,7);
5286         else 
5287           /* no need to compare to 0...*/
5288           /* NOTE: this is a de-generate compare that most certainly 
5289            *       creates some dead code. */
5290           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5291
5292         if(ifx) ifx->generated = 1;
5293         return;
5294
5295       }
5296       size--;
5297
5298       if(size == 0) {
5299         //i = (lit >> (size*8)) & 0xff;
5300         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5301         
5302         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5303
5304         i = ((0-lit) & 0xff);
5305         if(sign) {
5306           if( i == 0x81) { 
5307             /* lit is 0x7f, all signed chars are less than
5308              * this except for 0x7f itself */
5309             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5310             genSkipz2(&rFalseIfx,0);
5311           } else {
5312             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5313             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5314             genSkipc(&rFalseIfx);
5315           }
5316
5317         } else {
5318           if(lit == 1) {
5319             genSkipz2(&rFalseIfx,1);
5320           } else {
5321             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5322             genSkipc(&rFalseIfx);
5323           }
5324         }
5325
5326         if(ifx) ifx->generated = 1;
5327         return;
5328       }
5329
5330       /* chars are out of the way. now do ints and longs */
5331
5332
5333       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5334         
5335       /* special cases */
5336
5337       if(sign) {
5338
5339         if(lit == 0) {
5340           genSkipCond(&rFalseIfx,left,size,7);
5341           if(ifx) ifx->generated = 1;
5342           return;
5343         }
5344
5345         if(lit <0x100) {
5346           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5347
5348           //rFalseIfx.condition ^= 1;
5349           //genSkipCond(&rFalseIfx,left,size,7);
5350           //rFalseIfx.condition ^= 1;
5351
5352           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5353           if(rFalseIfx.condition)
5354             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5355           else
5356             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5357
5358           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5359           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5360           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5361
5362           while(size > 1)
5363             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5364
5365           if(rFalseIfx.condition) {
5366             emitSKPZ;
5367             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5368
5369           } else {
5370             emitSKPNZ;
5371           }
5372
5373           genSkipc(&rFalseIfx);
5374           pic16_emitpLabel(truelbl->key);
5375           if(ifx) ifx->generated = 1;
5376           return;
5377
5378         }
5379
5380         if(size == 1) {
5381
5382           if( (lit & 0xff) == 0) {
5383             /* lower byte is zero */
5384             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5385             i = ((lit >> 8) & 0xff) ^0x80;
5386             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5387             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5388             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5389             genSkipc(&rFalseIfx);
5390
5391
5392             if(ifx) ifx->generated = 1;
5393             return;
5394
5395           }
5396         } else {
5397           /* Special cases for signed longs */
5398           if( (lit & 0xffffff) == 0) {
5399             /* lower byte is zero */
5400             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5401             i = ((lit >> 8*3) & 0xff) ^0x80;
5402             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5403             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5404             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5405             genSkipc(&rFalseIfx);
5406
5407
5408             if(ifx) ifx->generated = 1;
5409             return;
5410
5411           }
5412
5413         }
5414
5415
5416         if(lit & (0x80 << (size*8))) {
5417           /* lit is negative */
5418           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5419
5420           //genSkipCond(&rFalseIfx,left,size,7);
5421
5422           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5423
5424           if(rFalseIfx.condition)
5425             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5426           else
5427             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5428
5429
5430         } else {
5431           /* lit is positive */
5432           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5433           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5434           if(rFalseIfx.condition)
5435             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5436           else
5437             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5438
5439         }
5440
5441         /*
5442           This works, but is only good for ints.
5443           It also requires a "known zero" register.
5444           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5445           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5446           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5447           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5448           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5449           genSkipc(&rFalseIfx);
5450
5451           pic16_emitpLabel(truelbl->key);
5452           if(ifx) ifx->generated = 1;
5453           return;
5454         **/
5455           
5456         /* There are no more special cases, so perform a general compare */
5457   
5458         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5459         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5460
5461         while(size--) {
5462
5463           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5464           emitSKPNZ;
5465           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5466         }
5467         //rFalseIfx.condition ^= 1;
5468         genSkipc(&rFalseIfx);
5469
5470         pic16_emitpLabel(truelbl->key);
5471
5472         if(ifx) ifx->generated = 1;
5473         return;
5474
5475
5476       }
5477
5478
5479       /* sign is out of the way. So now do an unsigned compare */
5480       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5481
5482
5483       /* General case - compare to an unsigned literal on the right.*/
5484
5485       i = (lit >> (size*8)) & 0xff;
5486       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5487       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5488       while(size--) {
5489         i = (lit >> (size*8)) & 0xff;
5490
5491         if(i) {
5492           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5493           emitSKPNZ;
5494           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5495         } else {
5496           /* this byte of the lit is zero, 
5497            *if it's not the last then OR in the variable */
5498           if(size)
5499             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5500         }
5501       }
5502
5503
5504       pic16_emitpLabel(lbl->key);
5505 //      pic16_emitpLabel(truelbl->key);
5506       //if(emitFinalCheck)
5507       genSkipc(&rFalseIfx);
5508       if(sign)
5509         pic16_emitpLabel(truelbl->key);
5510
5511       if(ifx) ifx->generated = 1;
5512       return;
5513
5514
5515     }
5516 #endif  // _swapp
5517
5518     if(AOP_TYPE(left) == AOP_LIT) {
5519       //symbol *lbl = newiTempLabel(NULL);
5520
5521       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5522
5523
5524       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5525
5526       /* Special cases */
5527       if((lit == 0) && (sign == 0)){
5528
5529         size--;
5530         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5531         while(size) 
5532           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5533
5534         genSkipz2(&rFalseIfx,0);
5535         if(ifx) ifx->generated = 1;
5536         return;
5537       }
5538
5539       if(size==1) {
5540         /* Special cases */
5541         lit &= 0xff;
5542         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5543           /* degenerate compare can never be true */
5544           if(rFalseIfx.condition == 0)
5545             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5546
5547           if(ifx) ifx->generated = 1;
5548           return;
5549         }
5550
5551         if(sign) {
5552           /* signed comparisons to a literal byte */
5553
5554           int lp1 = (lit+1) & 0xff;
5555
5556           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5557           switch (lp1) {
5558           case 0:
5559             rFalseIfx.condition ^= 1;
5560             genSkipCond(&rFalseIfx,right,0,7);
5561             break;
5562           case 0x7f:
5563             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5565             genSkipz2(&rFalseIfx,1);
5566             break;
5567           default:
5568             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5569             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5570             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5571             rFalseIfx.condition ^= 1;
5572             genSkipc(&rFalseIfx);
5573             break;
5574           }
5575         } else {
5576           /* unsigned comparisons to a literal byte */
5577
5578           switch(lit & 0xff ) {
5579           case 0:
5580             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5581             genSkipz2(&rFalseIfx,0);
5582             break;
5583           case 0x7f:
5584             rFalseIfx.condition ^= 1;
5585             genSkipCond(&rFalseIfx,right,0,7);
5586             break;
5587
5588           default:
5589             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5590             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5591             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5592             rFalseIfx.condition ^= 1;
5593             if (AOP_TYPE(result) == AOP_CRY)
5594               genSkipc(&rFalseIfx);
5595             else {
5596               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5597               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5598             }         
5599             break;
5600           }
5601         }
5602
5603         if(ifx) ifx->generated = 1;
5604         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5605                 goto check_carry;
5606         return;
5607
5608       } else {
5609
5610         /* Size is greater than 1 */
5611
5612         if(sign) {
5613           int lp1 = lit+1;
5614
5615           size--;
5616
5617           if(lp1 == 0) {
5618             /* this means lit = 0xffffffff, or -1 */
5619
5620
5621             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5622             rFalseIfx.condition ^= 1;
5623             genSkipCond(&rFalseIfx,right,size,7);
5624             if(ifx) ifx->generated = 1;
5625
5626             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5627               goto check_carry;
5628
5629             return;
5630           }
5631
5632           if(lit == 0) {
5633             int s = size;
5634
5635             if(rFalseIfx.condition) {
5636               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5637               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5638             }
5639
5640             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5641             while(size--)
5642               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5643
5644
5645             emitSKPZ;
5646             if(rFalseIfx.condition) {
5647               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5648               pic16_emitpLabel(truelbl->key);
5649             }else {
5650               rFalseIfx.condition ^= 1;
5651               genSkipCond(&rFalseIfx,right,s,7);
5652             }
5653
5654             if(ifx) ifx->generated = 1;
5655
5656             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5657               goto check_carry;
5658
5659             return;
5660           }
5661
5662           if((size == 1) &&  (0 == (lp1&0xff))) {
5663             /* lower byte of signed word is zero */
5664             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5665             i = ((lp1 >> 8) & 0xff) ^0x80;
5666             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5667             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5668             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5669
5670             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5671               emitTOGC;
5672               if(ifx) ifx->generated = 1;
5673               goto check_carry;
5674             } else {
5675               rFalseIfx.condition ^= 1;
5676               genSkipc(&rFalseIfx);
5677               if(ifx) ifx->generated = 1;
5678             }
5679
5680             return;
5681           }
5682
5683           if(lit & (0x80 << (size*8))) {
5684             /* Lit is less than zero */
5685             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5686             //rFalseIfx.condition ^= 1;
5687             //genSkipCond(&rFalseIfx,left,size,7);
5688             //rFalseIfx.condition ^= 1;
5689             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5690             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5691
5692             if(rFalseIfx.condition)
5693               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5694             else
5695               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5696
5697
5698           } else {
5699             /* Lit is greater than or equal to zero */
5700             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5701             //rFalseIfx.condition ^= 1;
5702             //genSkipCond(&rFalseIfx,right,size,7);
5703             //rFalseIfx.condition ^= 1;
5704
5705             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5706             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5707
5708             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5709             if(rFalseIfx.condition)
5710               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5711             else
5712               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5713
5714           }
5715
5716           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5717           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5718
5719           while(size--) {
5720
5721             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5722             emitSKPNZ;
5723             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5724           }
5725           rFalseIfx.condition ^= 1;
5726           //rFalseIfx.condition = 1;
5727           genSkipc(&rFalseIfx);
5728
5729           pic16_emitpLabel(truelbl->key);
5730
5731           if(ifx) ifx->generated = 1;
5732
5733
5734           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5735             goto check_carry;
5736
5737           return;
5738           // end of if (sign)
5739         } else {
5740
5741           /* compare word or long to an unsigned literal on the right.*/
5742
5743
5744           size--;
5745           if(lit < 0xff) {
5746             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5747             switch (lit) {
5748             case 0:
5749               break; /* handled above */
5750 /*
5751             case 0xff:
5752               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5753               while(size--)
5754                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5755               genSkipz2(&rFalseIfx,0);
5756               break;
5757 */
5758             default:
5759               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5760               while(--size)
5761                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5762
5763               emitSKPZ;
5764               if(rFalseIfx.condition)
5765                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5766               else
5767                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5768
5769
5770               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5771               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5772
5773               rFalseIfx.condition ^= 1;
5774               genSkipc(&rFalseIfx);
5775             }
5776
5777             pic16_emitpLabel(truelbl->key);
5778
5779             if(ifx) ifx->generated = 1;
5780
5781             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5782               goto check_carry;
5783
5784             return;
5785           }
5786
5787
5788           lit++;
5789           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5790           i = (lit >> (size*8)) & 0xff;
5791
5792           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5793           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5794
5795           while(size--) {
5796             i = (lit >> (size*8)) & 0xff;
5797
5798             if(i) {
5799               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5800               emitSKPNZ;
5801               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5802             } else {
5803               /* this byte of the lit is zero, 
5804                * if it's not the last then OR in the variable */
5805               if(size)
5806                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5807             }
5808           }
5809
5810
5811           pic16_emitpLabel(lbl->key);
5812
5813           rFalseIfx.condition ^= 1;
5814
5815           genSkipc(&rFalseIfx);
5816         }
5817
5818         if(sign)
5819           pic16_emitpLabel(truelbl->key);
5820         if(ifx) ifx->generated = 1;
5821
5822             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5823               goto check_carry;
5824
5825         return;
5826       }
5827     }
5828     /* Compare two variables */
5829
5830     DEBUGpic16_emitcode(";sign","%d",sign);
5831
5832     size--;
5833     if(sign) {
5834       /* Sigh. thus sucks... */
5835       if(size) {
5836         pCodeOp *pctemp;
5837         
5838         pctemp = pic16_popGetTempReg(1);
5839         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5840         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5841         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5842         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5843         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5844         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5845         pic16_popReleaseTempReg(pctemp, 1);
5846       } else {
5847         /* Signed char comparison */
5848         /* Special thanks to Nikolai Golovchenko for this snippet */
5849         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5850         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5851         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5852         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5853         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5854         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5855
5856         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5857         genSkipc(&rFalseIfx);
5858           
5859         if(ifx) ifx->generated = 1;
5860
5861             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5862               goto check_carry;
5863
5864         return;
5865       }
5866
5867     } else {
5868
5869       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5870       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5871     }
5872
5873
5874     /* The rest of the bytes of a multi-byte compare */
5875     while (size) {
5876
5877       emitSKPZ;
5878       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5879       size--;
5880
5881       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5882       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5883
5884
5885     }
5886
5887     pic16_emitpLabel(lbl->key);
5888
5889     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5890     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5891         (AOP_TYPE(result) == AOP_REG)) {
5892       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5893       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5894     } else {
5895       genSkipc(&rFalseIfx);
5896     }         
5897     //genSkipc(&rFalseIfx);
5898     if(ifx) ifx->generated = 1;
5899
5900
5901             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5902               goto check_carry;
5903
5904     return;
5905
5906   }
5907
5908 check_carry:
5909   if ((AOP_TYPE(result) != AOP_CRY) 
5910         && AOP_SIZE(result)) {
5911     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5912
5913     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5914
5915     pic16_outBitC(result);
5916   } else {
5917     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5918     /* if the result is used in the next
5919        ifx conditional branch then generate
5920        code a little differently */
5921     if (ifx )
5922       genIfxJump (ifx,"c");
5923     else
5924       pic16_outBitC(result);
5925     /* leave the result in acc */
5926   }
5927
5928 }
5929
5930 #elif 0 /* VR version of genCmp() */    /* } else { */
5931
5932 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5933 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5934         operand *result, int offset, int invert_op)
5935 {
5936   /* add code here */
5937   
5938   /* check condition, > or < ?? */
5939   if(rIfx->condition != 0)invert_op ^= 1;
5940   
5941   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5942
5943   if(!ifx)invert_op ^= 1;
5944
5945   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5946       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5947   
5948   /* do selection */
5949   if(!invert_op)return POC_CPFSGT;
5950   else return POC_CPFSLT;
5951 }
5952
5953 static int compareAopfirstpass=1;
5954
5955 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5956             operand *oper, int offset, operand *result,
5957             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5958             symbol *tlbl)
5959 {
5960   int op;
5961   symbol *truelbl;
5962
5963   /* invert if there is a result to be loaded, in order to fit,
5964    * SETC/CLRC sequence */
5965   if(AOP_SIZE(result))invert_op ^= 1;
5966
5967 //  if(sign && !offset)invert_op ^= 1;
5968   
5969 //  if(sign)invert_op ^= 1;
5970   
5971   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5972
5973   if(AOP_SIZE(result) && compareAopfirstpass) {
5974     if(!ifx) {
5975       if(pcop2)
5976         pic16_emitpcode(POC_SETF, pcop2);
5977       else
5978         emitSETC;
5979     } else {
5980       if(pcop2)
5981         pic16_emitpcode(POC_CLRF, pcop2);
5982       else
5983         emitCLRC;
5984     }
5985   }
5986
5987   compareAopfirstpass = 0;
5988
5989       /* there is a bug when comparing operands with size > 1,
5990        * because higher bytes can be equal and test should be performed
5991        * to the next lower byte, current algorithm, considers operands
5992        * inequal in these cases! -- VR 20041107 */
5993
5994     
5995   if(pcop)
5996     pic16_emitpcode(op, pcop);
5997   else
5998     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5999
6000
6001   if((!sign || !offset) && AOP_SIZE(result)) {
6002     if(!ifx) {
6003       if(pcop2)
6004         pic16_emitpcode(POC_CLRF, pcop2);
6005         else
6006         emitCLRC;
6007     } else {
6008       if(pcop2)
6009         pic16_emitpcode(POC_SETF, pcop2);
6010       else
6011         emitSETC;
6012     }
6013     
6014     /* don't emit final branch (offset == 0) */
6015     if(offset) {
6016
6017       if(pcop2)
6018         pic16_emitpcode(POC_RRCF, pcop2);
6019
6020       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6021     }
6022   } else {
6023     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6024       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6025             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6026
6027       truelbl = newiTempLabel( NULL );
6028       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6029       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6030         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6031       else
6032         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6033       pic16_emitpLabel(truelbl->key);
6034     } else {
6035       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6036     }
6037   }
6038 }
6039
6040 static void genCmp (operand *left, operand *right,
6041                     operand *result, iCode *ifx, int sign)
6042 {
6043   int size, cmpop=1;
6044   long lit = 0L;
6045   resolvedIfx rFalseIfx;
6046   symbol *falselbl, *tlbl;
6047
6048     FENTRY;
6049     
6050     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6051
6052     resolveIfx(&rFalseIfx, ifx);
6053     size = max(AOP_SIZE(left), AOP_SIZE(right));
6054     
6055     /* if left & right are bit variables */
6056     if(AOP_TYPE(left) == AOP_CRY
6057       && AOP_TYPE(right) == AOP_CRY ) {
6058
6059         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6060         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6061         
6062         werror(W_POSSBUG2, __FILE__, __LINE__);
6063         exit(-1);
6064     }
6065     
6066     /* if literal is on the right then swap with left */
6067     if((AOP_TYPE(right) == AOP_LIT)) {
6068       operand *tmp = right ;
6069 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6070
6071         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6072
6073 //      lit = (lit - 1) & mask;
6074         right = left;
6075         left = tmp;
6076         rFalseIfx.condition ^= 1;               /* reverse compare */
6077     } else
6078     if ((AOP_TYPE(left) == AOP_LIT)) {
6079       /* float compares are handled by support functions */
6080       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6081     }
6082
6083     /* actual comparing algorithm */
6084 //    size = AOP_SIZE( right );
6085
6086     falselbl = newiTempLabel( NULL );
6087     if(AOP_TYPE(left) == AOP_LIT) {
6088       /* compare to literal */
6089       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6090       
6091       if(sign) {
6092         pCodeOp *pct, *pct2;
6093         symbol *tlbl1;
6094
6095         /* signed compare */
6096         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6097
6098         /* using PRODL:PRODH as a temporary register here */
6099         pct = pic16_popCopyReg(&pic16_pc_prodl);
6100         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6101         tlbl = newiTempLabel( NULL );
6102         
6103         /* first compare signs:
6104          *  a. if both are positive, compare just like unsigned
6105          *  b. if both are negative, invert cmpop, compare just like unsigned
6106          *  c. if different signs, determine the result directly */
6107
6108         size--;
6109
6110 #if 1
6111         /* { */
6112         tlbl1 = newiTempLabel( NULL );
6113 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6114
6115         if(lit > 0) {
6116
6117           /* literal is zero or positive:
6118            *  a. if carry is zero, too, continue compare,
6119            *  b. if carry is set, then continue depending on cmpop ^ condition:
6120            *    1. '<' return false (literal < variable),
6121            *    2. '>' return true (literal > variable) */
6122 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6123           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6124           
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         } else 
6129         if(lit < 0) {
6130           
6131           /* literal is negative:
6132            *  a. if carry is set, too, continue compare,
6133            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6134            *    1. '<' return true (literal < variable),
6135            *    2. '>' return false (literal > variable) */
6136 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6137           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6138           
6139           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6140           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6141         }
6142 #if 1
6143         else {
6144           /* lit == 0 */
6145           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6146           
6147           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6148           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6149         }
6150 #endif
6151         
6152         
6153         pic16_emitpLabel( tlbl1->key );
6154 #endif  /* } */
6155
6156         compareAopfirstpass=1;
6157 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6158 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6159 //        pic16_emitpcode(POC_MOVWF, pct);
6160
6161 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6162         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6163 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6165
6166         /* generic case */        
6167           while( size-- ) {
6168 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6169 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6170 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6171 //            pic16_emitpcode(POC_MOVWF, pct);
6172
6173 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6174             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6175             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6176 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6177 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6178           }
6179         
6180         if(ifx)ifx->generated = 1;
6181
6182         if(AOP_SIZE(result)) {
6183           pic16_emitpLabel(tlbl->key);
6184           pic16_emitpLabel(falselbl->key);
6185           pic16_outBitOp( result, pct2 );
6186         } else {
6187           pic16_emitpLabel(tlbl->key);
6188         }
6189       } else {
6190
6191         /* unsigned compare */      
6192         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6193     
6194         compareAopfirstpass=1;
6195         while(size--) {
6196           
6197           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6198           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6199
6200         }
6201         if(ifx)ifx->generated = 1;
6202
6203         if(AOP_SIZE(result)) {
6204           pic16_emitpLabel(falselbl->key);
6205           pic16_outBitC( result );
6206         }
6207
6208       }
6209     } else {
6210       /* compare registers */
6211       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6212
6213
6214       if(sign) {
6215         pCodeOp *pct, *pct2;
6216         
6217         /* signed compare */
6218         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6219
6220         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6221         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6222         tlbl = newiTempLabel( NULL );
6223         
6224         compareAopfirstpass=1;
6225
6226         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         
6239         while( size-- ) {
6240           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6241 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6242           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6243           pic16_emitpcode(POC_MOVWF, pct);
6244                 
6245           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6246 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6247           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6248
6249           /* WREG already holds left + 0x80 */
6250           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6251 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6252         }
6253         
6254         if(ifx)ifx->generated = 1;
6255
6256         if(AOP_SIZE(result)) {
6257           pic16_emitpLabel(tlbl->key);
6258           pic16_emitpLabel(falselbl->key);
6259           pic16_outBitOp( result, pct2 );
6260         } else {
6261           pic16_emitpLabel(tlbl->key);
6262         }
6263
6264       } else {
6265         /* unsigned compare */      
6266         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6267
6268         compareAopfirstpass=1;
6269         while(size--) {
6270           
6271           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6272           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6273
6274         }
6275
6276         if(ifx)ifx->generated = 1;
6277         if(AOP_SIZE(result)) {
6278
6279           pic16_emitpLabel(falselbl->key);
6280           pic16_outBitC( result );
6281         }
6282
6283       }
6284     }
6285 }
6286
6287 #endif  /* } */
6288
6289
6290
6291 /*-----------------------------------------------------------------*/
6292 /* genCmpGt :- greater than comparison                             */
6293 /*-----------------------------------------------------------------*/
6294 static void genCmpGt (iCode *ic, iCode *ifx)
6295 {
6296   operand *left, *right, *result;
6297   sym_link *letype , *retype;
6298   int sign ;
6299
6300     FENTRY;
6301     
6302     left = IC_LEFT(ic);
6303     right= IC_RIGHT(ic);
6304     result = IC_RESULT(ic);
6305
6306     letype = getSpec(operandType(left));
6307     retype =getSpec(operandType(right));
6308     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6309     /* assign the amsops */
6310     pic16_aopOp (left,ic,FALSE);
6311     pic16_aopOp (right,ic,FALSE);
6312     pic16_aopOp (result,ic,TRUE);
6313
6314     genCmp(right, left, result, ifx, sign);
6315
6316     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6317     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6318     pic16_freeAsmop(result,NULL,ic,TRUE); 
6319 }
6320
6321 /*-----------------------------------------------------------------*/
6322 /* genCmpLt - less than comparisons                                */
6323 /*-----------------------------------------------------------------*/
6324 static void genCmpLt (iCode *ic, iCode *ifx)
6325 {
6326   operand *left, *right, *result;
6327   sym_link *letype , *retype;
6328   int sign ;
6329
6330     FENTRY;
6331
6332     left = IC_LEFT(ic);
6333     right= IC_RIGHT(ic);
6334     result = IC_RESULT(ic);
6335
6336     letype = getSpec(operandType(left));
6337     retype =getSpec(operandType(right));
6338     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6339
6340     /* assign the amsops */
6341     pic16_aopOp (left,ic,FALSE);
6342     pic16_aopOp (right,ic,FALSE);
6343     pic16_aopOp (result,ic,TRUE);
6344
6345     genCmp(left, right, result, ifx, sign);
6346
6347     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6348     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6349     pic16_freeAsmop(result,NULL,ic,TRUE); 
6350 }
6351
6352 #if 0
6353 // not needed ATM
6354 // FIXME reenable literal optimisation when the pic16 port is stable
6355
6356 /*-----------------------------------------------------------------*/
6357 /* genc16bit2lit - compare a 16 bit value to a literal             */
6358 /*-----------------------------------------------------------------*/
6359 static void genc16bit2lit(operand *op, int lit, int offset)
6360 {
6361   int i;
6362
6363   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6364   if( (lit&0xff) == 0) 
6365     i=1;
6366   else
6367     i=0;
6368
6369   switch( BYTEofLONG(lit,i)) { 
6370   case 0:
6371     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6372     break;
6373   case 1:
6374     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   case 0xff:
6377     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6378     break;
6379   default:
6380     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6381     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6382   }
6383
6384   i ^= 1;
6385
6386   switch( BYTEofLONG(lit,i)) { 
6387   case 0:
6388     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6389     break;
6390   case 1:
6391     emitSKPNZ;
6392     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6393     break;
6394   case 0xff:
6395     emitSKPNZ;
6396     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6397     break;
6398   default:
6399     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6400     emitSKPNZ;
6401     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6402
6403   }
6404
6405 }
6406 #endif
6407
6408 #if 0
6409 // not needed ATM
6410 /*-----------------------------------------------------------------*/
6411 /* gencjneshort - compare and jump if not equal                    */
6412 /*-----------------------------------------------------------------*/
6413 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6414 {
6415   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6416   int offset = 0;
6417   int res_offset = 0;  /* the result may be a different size then left or right */
6418   int res_size = AOP_SIZE(result);
6419   resolvedIfx rIfx;
6420   symbol *lbl, *lbl_done;
6421
6422   unsigned long lit = 0L;
6423   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6424
6425   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6426   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6427   if(result)
6428     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6429   resolveIfx(&rIfx,ifx);
6430   lbl =  newiTempLabel(NULL);
6431   lbl_done =  newiTempLabel(NULL);
6432
6433
6434   /* if the left side is a literal or 
6435      if the right is in a pointer register and left 
6436      is not */
6437   if ((AOP_TYPE(left) == AOP_LIT) || 
6438       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6439     operand *t = right;
6440     right = left;
6441     left = t;
6442   }
6443   if(AOP_TYPE(right) == AOP_LIT)
6444     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6445
6446   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6447     preserve_result = 1;
6448
6449   if(result && !preserve_result)
6450     {
6451       int i;
6452       for(i = 0; i < AOP_SIZE(result); i++)
6453         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6454     }
6455
6456
6457   /* if the right side is a literal then anything goes */
6458   if (AOP_TYPE(right) == AOP_LIT &&
6459       AOP_TYPE(left) != AOP_DIR ) {
6460     switch(size) {
6461     case 2:
6462       genc16bit2lit(left, lit, 0);
6463       emitSKPZ;
6464       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6465       break;
6466     default:
6467       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6468       while (size--) {
6469         if(lit & 0xff) {
6470           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6471           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6472         } else {
6473           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6474         }
6475
6476         emitSKPZ;
6477         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6478         offset++;
6479         if(res_offset < res_size-1)
6480           res_offset++;
6481         lit >>= 8;
6482       }
6483       break;
6484     }
6485   }
6486
6487   /* if the right side is in a register or in direct space or
6488      if the left is a pointer register & right is not */    
6489   else if (AOP_TYPE(right) == AOP_REG ||
6490            AOP_TYPE(right) == AOP_DIR || 
6491            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6492            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6493     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6494     int lbl_key = lbl->key;
6495
6496     if(result) {
6497       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6498       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6499     }else {
6500       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6501       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6502               __FUNCTION__,__LINE__);
6503       return;
6504     }
6505    
6506 /*     switch(size) { */
6507 /*     case 2: */
6508 /*       genc16bit2lit(left, lit, 0); */
6509 /*       emitSKPNZ; */
6510 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6511 /*       break; */
6512 /*     default: */
6513     while (size--) {
6514       int emit_skip=1;
6515       if((AOP_TYPE(left) == AOP_DIR) && 
6516          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6517
6518         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6519         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6520
6521       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6522             
6523         switch (lit & 0xff) {
6524         case 0:
6525           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6526           break;
6527         case 1:
6528           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6529           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6530           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6531           emit_skip=0;
6532           break;
6533         case 0xff:
6534           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6535           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6536           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6537           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6538           emit_skip=0;
6539           break;
6540         default:
6541           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6542           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6543         }
6544         lit >>= 8;
6545
6546       } else {
6547         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6548       }
6549       if(emit_skip) {
6550         if(AOP_TYPE(result) == AOP_CRY) {
6551           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6552           if(rIfx.condition)
6553             emitSKPNZ;
6554           else
6555             emitSKPZ;
6556           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6557         } else {
6558           /* fix me. probably need to check result size too */
6559           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6560           if(rIfx.condition)
6561             emitSKPZ;
6562           else
6563             emitSKPNZ;
6564           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6565           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6566         }
6567         if(ifx)
6568           ifx->generated=1;
6569       }
6570       emit_skip++;
6571       offset++;
6572       if(res_offset < res_size-1)
6573         res_offset++;
6574     }
6575 /*       break; */
6576 /*     } */
6577   } else if(AOP_TYPE(right) == AOP_REG &&
6578             AOP_TYPE(left) != AOP_DIR){
6579
6580     while(size--) {
6581       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6582       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6583       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6584       if(rIfx.condition)
6585         emitSKPNZ;
6586       else
6587         emitSKPZ;
6588       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6589       offset++;
6590       if(res_offset < res_size-1)
6591         res_offset++;
6592     }
6593       
6594   }else{
6595     /* right is a pointer reg need both a & b */
6596     while(size--) {
6597       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6598       if(strcmp(l,"b"))
6599         pic16_emitcode("mov","b,%s",l);
6600       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6601       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6602       offset++;
6603     }
6604   }
6605
6606   if(result && preserve_result)
6607     {
6608       int i;
6609       for(i = 0; i < AOP_SIZE(result); i++)
6610         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6611     }
6612
6613   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6614
6615   if(result && preserve_result)
6616     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6617
6618   if(!rIfx.condition)
6619     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6620
6621   pic16_emitpLabel(lbl->key);
6622
6623   if(result && preserve_result)
6624     {
6625       int i;
6626       for(i = 0; i < AOP_SIZE(result); i++)
6627         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6628
6629       pic16_emitpLabel(lbl_done->key);
6630    }
6631
6632   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6633
6634   if(ifx)
6635     ifx->generated = 1;
6636 }
6637 #endif
6638
6639 #if 0
6640 /*-----------------------------------------------------------------*/
6641 /* gencjne - compare and jump if not equal                         */
6642 /*-----------------------------------------------------------------*/
6643 static void gencjne(operand *left, operand *right, iCode *ifx)
6644 {
6645     symbol *tlbl  = newiTempLabel(NULL);
6646
6647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6648     gencjneshort(left, right, lbl);
6649
6650     pic16_emitcode("mov","a,%s",one);
6651     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6652     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6653     pic16_emitcode("clr","a");
6654     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6655
6656     pic16_emitpLabel(lbl->key);
6657     pic16_emitpLabel(tlbl->key);
6658
6659 }
6660 #endif
6661
6662
6663 /*-----------------------------------------------------------------*/
6664 /* is_LitOp - check if operand has to be treated as literal        */
6665 /*-----------------------------------------------------------------*/
6666 static bool is_LitOp(operand *op)
6667 {
6668   return ((AOP_TYPE(op) == AOP_LIT)
6669       || ( (AOP_TYPE(op) == AOP_PCODE)
6670           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6671               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6672 }
6673
6674 /*-----------------------------------------------------------------*/
6675 /* is_LitAOp - check if operand has to be treated as literal        */
6676 /*-----------------------------------------------------------------*/
6677 static bool is_LitAOp(asmop *aop)
6678 {
6679   return ((aop->type == AOP_LIT)
6680       || ( (aop->type == AOP_PCODE)
6681           && ( (aop->aopu.pcop->type == PO_LITERAL)
6682               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6683 }
6684
6685
6686
6687 /*-----------------------------------------------------------------*/
6688 /* genCmpEq - generates code for equal to                          */
6689 /*-----------------------------------------------------------------*/
6690 static void genCmpEq (iCode *ic, iCode *ifx)
6691 {
6692   operand *left, *right, *result;
6693   symbol *falselbl = newiTempLabel(NULL);
6694   symbol *donelbl = newiTempLabel(NULL);
6695
6696   int preserve_result = 0;
6697   int generate_result = 0;
6698   int i=0;
6699   unsigned long lit = -1;
6700
6701   FENTRY;
6702   
6703   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6704   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6705   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6706  
6707   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6708
6709   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6710     {
6711       werror(W_POSSBUG2, __FILE__, __LINE__);
6712       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6713       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6714       goto release;
6715     }
6716
6717   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6718     {
6719       operand *tmp = right ;
6720       right = left;
6721       left = tmp;
6722     }
6723
6724   if (AOP_TYPE(right) == AOP_LIT) {
6725     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6726   }
6727
6728   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6729     preserve_result = 1;
6730
6731   if(result && AOP_SIZE(result))
6732     generate_result = 1;
6733
6734   if(generate_result && !preserve_result)
6735     {
6736       for(i = 0; i < AOP_SIZE(result); i++)
6737         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6738     }
6739
6740   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6741   for(i=0; i < AOP_SIZE(left); i++)
6742     {
6743       if(AOP_TYPE(left) != AOP_ACC)
6744         {
6745           if(is_LitOp(left))
6746             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6747           else
6748             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6749         }
6750       if(is_LitOp(right)) {
6751         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6752           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6753         }
6754       } else
6755         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6756
6757       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6758     }
6759
6760   // result == true
6761
6762   if(generate_result && preserve_result)
6763     {
6764       for(i = 0; i < AOP_SIZE(result); i++)
6765         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6766     }
6767
6768   if(generate_result)
6769     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6770
6771   if(generate_result && preserve_result)
6772     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6773
6774   if(ifx && IC_TRUE(ifx))
6775     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6776
6777   if(ifx && IC_FALSE(ifx))
6778     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6779
6780   pic16_emitpLabel(falselbl->key);
6781
6782   // result == false
6783
6784   if(ifx && IC_FALSE(ifx))
6785     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6786
6787   if(generate_result && preserve_result)
6788     {
6789       for(i = 0; i < AOP_SIZE(result); i++)
6790         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6791     }
6792
6793   pic16_emitpLabel(donelbl->key);
6794
6795   if(ifx)
6796     ifx->generated = 1;
6797
6798 release:
6799   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6800   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6801   pic16_freeAsmop(result,NULL,ic,TRUE);
6802
6803 }
6804
6805
6806 #if 0
6807 // old version kept for reference
6808
6809 /*-----------------------------------------------------------------*/
6810 /* genCmpEq - generates code for equal to                          */
6811 /*-----------------------------------------------------------------*/
6812 static void genCmpEq (iCode *ic, iCode *ifx)
6813 {
6814     operand *left, *right, *result;
6815     unsigned long lit = 0L;
6816     int size,offset=0;
6817     symbol *falselbl  = newiTempLabel(NULL);
6818
6819
6820     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6821
6822     if(ifx)
6823       DEBUGpic16_emitcode ("; ifx is non-null","");
6824     else
6825       DEBUGpic16_emitcode ("; ifx is null","");
6826
6827     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6828     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6829     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6830
6831     size = max(AOP_SIZE(left),AOP_SIZE(right));
6832
6833     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6834
6835     /* if literal, literal on the right or 
6836     if the right is in a pointer register and left 
6837     is not */
6838     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6839         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6840       operand *tmp = right ;
6841       right = left;
6842       left = tmp;
6843     }
6844
6845
6846     if(ifx && !AOP_SIZE(result)){
6847         symbol *tlbl;
6848         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6849         /* if they are both bit variables */
6850         if (AOP_TYPE(left) == AOP_CRY &&
6851             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6852                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6853             if(AOP_TYPE(right) == AOP_LIT){
6854                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6855                 if(lit == 0L){
6856                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6857                     pic16_emitcode("cpl","c");
6858                 } else if(lit == 1L) {
6859                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6860                 } else {
6861                     pic16_emitcode("clr","c");
6862                 }
6863                 /* AOP_TYPE(right) == AOP_CRY */
6864             } else {
6865                 symbol *lbl = newiTempLabel(NULL);
6866                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6867                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6868                 pic16_emitcode("cpl","c");
6869                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6870             }
6871             /* if true label then we jump if condition
6872             supplied is true */
6873             tlbl = newiTempLabel(NULL);
6874             if ( IC_TRUE(ifx) ) {
6875                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6876                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6877             } else {
6878                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6879                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6880             }
6881             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6882
6883                 {
6884                 /* left and right are both bit variables, result is carry */
6885                         resolvedIfx rIfx;
6886               
6887                         resolveIfx(&rIfx,ifx);
6888
6889                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6890                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6891                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6892                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6893                         genSkipz2(&rIfx,0);
6894                 }
6895         } else {
6896
6897                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6898
6899                         /* They're not both bit variables. Is the right a literal? */
6900                         if(AOP_TYPE(right) == AOP_LIT) {
6901                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6902             
6903                         switch(size) {
6904
6905                                 case 1:
6906                                         switch(lit & 0xff) {
6907                                                 case 1:
6908                                                                 if ( IC_TRUE(ifx) ) {
6909                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6910                                                                         emitSKPNZ;
6911                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6912                                                                 } else {
6913                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6914                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6915                                                                 }
6916                                                                 break;
6917                                                 case 0xff:
6918                                                                 if ( IC_TRUE(ifx) ) {
6919                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6920                                                                         emitSKPNZ;
6921                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6922                                                                 } else {
6923                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6924                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6925                                                                 }
6926                                                                 break;
6927                                                 default:
6928                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6929                                                                 if(lit)
6930                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6931                                                                 genSkip(ifx,'z');
6932                                         } // switch lit
6933
6934
6935                                         /* end of size == 1 */
6936                                         break;
6937               
6938                                 case 2:
6939                                         genc16bit2lit(left,lit,offset);
6940                                         genSkip(ifx,'z');
6941                                         break;
6942                                         /* end of size == 2 */
6943
6944                                 default:
6945                                         /* size is 4 */
6946                                         if(lit==0) {
6947                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6948                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6949                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6950                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6951                                                 genSkip(ifx,'z');
6952                                         } else {
6953                                                 /* search for patterns that can be optimized */
6954
6955                                                 genc16bit2lit(left,lit,0);
6956                                                 lit >>= 16;
6957                                                 if(lit) {
6958                                                                 if(IC_TRUE(ifx))
6959                                                                 emitSKPZ; // if hi word unequal
6960                                                                 else
6961                                                                 emitSKPNZ; // if hi word equal
6962                                                                 // fail early
6963                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6964                                                         genc16bit2lit(left,lit,2);
6965                                                         genSkip(ifx,'z');
6966                                                 } else {
6967                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6968                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6969                                                         genSkip(ifx,'z');
6970                                                 }
6971                                         }
6972                                                 pic16_emitpLabel(falselbl->key);
6973                                                 break;
6974
6975                         } // switch size
6976           
6977                         ifx->generated = 1;
6978                         goto release ;
6979             
6980
6981           } else if(AOP_TYPE(right) == AOP_CRY ) {
6982             /* we know the left is not a bit, but that the right is */
6983             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6984             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6985                       pic16_popGet(AOP(right),offset));
6986             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6987
6988             /* if the two are equal, then W will be 0 and the Z bit is set
6989              * we could test Z now, or go ahead and check the high order bytes if
6990              * the variable we're comparing is larger than a byte. */
6991
6992             while(--size)
6993               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6994
6995             if ( IC_TRUE(ifx) ) {
6996               emitSKPNZ;
6997               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6998               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6999             } else {
7000               emitSKPZ;
7001               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7002               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7003             }
7004
7005           } else {
7006             /* They're both variables that are larger than bits */
7007             int s = size;
7008
7009             tlbl = newiTempLabel(NULL);
7010
7011             while(size--) {
7012               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7013               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7014
7015               if ( IC_TRUE(ifx) ) {
7016                 if(size) {
7017                   emitSKPZ;
7018                 
7019                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7020
7021                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7022                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7023                 } else {
7024                   emitSKPNZ;
7025
7026                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7027
7028
7029                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7030                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7031                 }
7032               } else {
7033                 emitSKPZ;
7034
7035                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7036
7037                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7038                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7039               }
7040               offset++;
7041             }
7042             if(s>1 && IC_TRUE(ifx)) {
7043               pic16_emitpLabel(tlbl->key);
7044               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7045             }
7046           }
7047         }
7048         /* mark the icode as generated */
7049         ifx->generated = 1;
7050         goto release ;
7051     }
7052
7053     /* if they are both bit variables */
7054     if (AOP_TYPE(left) == AOP_CRY &&
7055         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7056         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7057         if(AOP_TYPE(right) == AOP_LIT){
7058             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7059             if(lit == 0L){
7060                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7061                 pic16_emitcode("cpl","c");
7062             } else if(lit == 1L) {
7063                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7064             } else {
7065                 pic16_emitcode("clr","c");
7066             }
7067             /* AOP_TYPE(right) == AOP_CRY */
7068         } else {
7069             symbol *lbl = newiTempLabel(NULL);
7070             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7071             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7072             pic16_emitcode("cpl","c");
7073             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7074         }
7075         /* c = 1 if egal */
7076         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7077             pic16_outBitC(result);
7078             goto release ;
7079         }
7080         if (ifx) {
7081             genIfxJump (ifx,"c");
7082             goto release ;
7083         }
7084         /* if the result is used in an arithmetic operation
7085         then put the result in place */
7086         pic16_outBitC(result);
7087     } else {
7088       
7089       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7090       gencjne(left,right,result,ifx);
7091 /*
7092       if(ifx) 
7093         gencjne(left,right,newiTempLabel(NULL));
7094       else {
7095         if(IC_TRUE(ifx)->key)
7096           gencjne(left,right,IC_TRUE(ifx)->key);
7097         else
7098           gencjne(left,right,IC_FALSE(ifx)->key);
7099         ifx->generated = 1;
7100         goto release ;
7101       }
7102       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7103         pic16_aopPut(AOP(result),"a",0);
7104         goto release ;
7105       }
7106
7107       if (ifx) {
7108         genIfxJump (ifx,"a");
7109         goto release ;
7110       }
7111 */
7112       /* if the result is used in an arithmetic operation
7113          then put the result in place */
7114 /*
7115       if (AOP_TYPE(result) != AOP_CRY) 
7116         pic16_outAcc(result);
7117 */
7118       /* leave the result in acc */
7119     }
7120
7121 release:
7122     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7123     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7124     pic16_freeAsmop(result,NULL,ic,TRUE);
7125 }
7126 #endif
7127
7128 /*-----------------------------------------------------------------*/
7129 /* ifxForOp - returns the icode containing the ifx for operand     */
7130 /*-----------------------------------------------------------------*/
7131 static iCode *ifxForOp ( operand *op, iCode *ic )
7132 {
7133   FENTRY2;
7134
7135     /* if true symbol then needs to be assigned */
7136     if (IS_TRUE_SYMOP(op))
7137         return NULL ;
7138
7139     /* if this has register type condition and
7140     the next instruction is ifx with the same operand
7141     and live to of the operand is upto the ifx only then */
7142     if (ic->next
7143         && ic->next->op == IFX
7144         && IC_COND(ic->next)->key == op->key
7145         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7146         ) {
7147                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7148           return ic->next;
7149     }
7150
7151     /*
7152     if (ic->next &&
7153         ic->next->op == IFX &&
7154         IC_COND(ic->next)->key == op->key) {
7155       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7156       return ic->next;
7157     }
7158     */
7159
7160     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7161     if (ic->next &&
7162         ic->next->op == IFX)
7163       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7164
7165     if (ic->next &&
7166         ic->next->op == IFX &&
7167         IC_COND(ic->next)->key == op->key) {
7168       DEBUGpic16_emitcode ("; "," key is okay");
7169       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7170                            OP_SYMBOL(op)->liveTo,
7171                            ic->next->seq);
7172     }
7173
7174 #if 0
7175     /* the code below is completely untested
7176      * it just allows ulong2fs.c compile -- VR */
7177          
7178     ic = ic->next;
7179     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7180                                         __FILE__, __FUNCTION__, __LINE__);
7181         
7182     /* if this has register type condition and
7183     the next instruction is ifx with the same operand
7184     and live to of the operand is upto the ifx only then */
7185     if (ic->next &&
7186         ic->next->op == IFX &&
7187         IC_COND(ic->next)->key == op->key &&
7188         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7189         return ic->next;
7190
7191     if (ic->next &&
7192         ic->next->op == IFX &&
7193         IC_COND(ic->next)->key == op->key) {
7194       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7195       return ic->next;
7196     }
7197
7198     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7199                                         __FILE__, __FUNCTION__, __LINE__);
7200
7201 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7202 #endif
7203
7204     return NULL;
7205 }
7206 /*-----------------------------------------------------------------*/
7207 /* genAndOp - for && operation                                     */
7208 /*-----------------------------------------------------------------*/
7209 static void genAndOp (iCode *ic)
7210 {
7211   operand *left,*right, *result;
7212 /*     symbol *tlbl; */
7213
7214     FENTRY;
7215
7216     /* note here that && operations that are in an
7217     if statement are taken away by backPatchLabels
7218     only those used in arthmetic operations remain */
7219     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7220     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7221     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7222
7223     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7224
7225     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7226     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7227     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7228
7229     /* if both are bit variables */
7230 /*     if (AOP_TYPE(left) == AOP_CRY && */
7231 /*         AOP_TYPE(right) == AOP_CRY ) { */
7232 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7233 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7234 /*         pic16_outBitC(result); */
7235 /*     } else { */
7236 /*         tlbl = newiTempLabel(NULL); */
7237 /*         pic16_toBoolean(left);     */
7238 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7239 /*         pic16_toBoolean(right); */
7240 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7241 /*         pic16_outBitAcc(result); */
7242 /*     } */
7243
7244     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7245     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7246     pic16_freeAsmop(result,NULL,ic,TRUE);
7247 }
7248
7249
7250 /*-----------------------------------------------------------------*/
7251 /* genOrOp - for || operation                                      */
7252 /*-----------------------------------------------------------------*/
7253 /*
7254   tsd pic port -
7255   modified this code, but it doesn't appear to ever get called
7256 */
7257
7258 static void genOrOp (iCode *ic)
7259 {
7260   operand *left,*right, *result;
7261   symbol *tlbl;
7262
7263     FENTRY;  
7264
7265   /* note here that || operations that are in an
7266     if statement are taken away by backPatchLabels
7267     only those used in arthmetic operations remain */
7268     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7269     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7270     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7271
7272     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7273
7274     /* if both are bit variables */
7275     if (AOP_TYPE(left) == AOP_CRY &&
7276         AOP_TYPE(right) == AOP_CRY ) {
7277       pic16_emitcode("clrc","");
7278       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7279                AOP(left)->aopu.aop_dir,
7280                AOP(left)->aopu.aop_dir);
7281       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7282                AOP(right)->aopu.aop_dir,
7283                AOP(right)->aopu.aop_dir);
7284       pic16_emitcode("setc","");
7285
7286     } else {
7287         tlbl = newiTempLabel(NULL);
7288         pic16_toBoolean(left);
7289         emitSKPZ;
7290         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7291         pic16_toBoolean(right);
7292         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7293
7294         pic16_outBitAcc(result);
7295     }
7296
7297     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7298     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7299     pic16_freeAsmop(result,NULL,ic,TRUE);            
7300 }
7301
7302 /*-----------------------------------------------------------------*/
7303 /* isLiteralBit - test if lit == 2^n                               */
7304 /*-----------------------------------------------------------------*/
7305 static int isLiteralBit(unsigned long lit)
7306 {
7307     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7308     0x100L,0x200L,0x400L,0x800L,
7309     0x1000L,0x2000L,0x4000L,0x8000L,
7310     0x10000L,0x20000L,0x40000L,0x80000L,
7311     0x100000L,0x200000L,0x400000L,0x800000L,
7312     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7313     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7314     int idx;
7315     
7316     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7317     for(idx = 0; idx < 32; idx++)
7318         if(lit == pw[idx])
7319             return idx+1;
7320     return 0;
7321 }
7322
7323 /*-----------------------------------------------------------------*/
7324 /* continueIfTrue -                                                */
7325 /*-----------------------------------------------------------------*/
7326 static void continueIfTrue (iCode *ic)
7327 {
7328   FENTRY;
7329   if(IC_TRUE(ic))
7330     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7331   ic->generated = 1;
7332 }
7333
7334 /*-----------------------------------------------------------------*/
7335 /* jmpIfTrue -                                                     */
7336 /*-----------------------------------------------------------------*/
7337 static void jumpIfTrue (iCode *ic)
7338 {
7339   FENTRY;
7340   if(!IC_TRUE(ic))
7341     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7342   ic->generated = 1;
7343 }
7344
7345 /*-----------------------------------------------------------------*/
7346 /* jmpTrueOrFalse -                                                */
7347 /*-----------------------------------------------------------------*/
7348 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7349 {
7350   // ugly but optimized by peephole
7351   FENTRY;
7352   if(IC_TRUE(ic)){
7353     symbol *nlbl = newiTempLabel(NULL);
7354       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7355       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7356       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7357       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7358   } else {
7359     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7360     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7361   }
7362   ic->generated = 1;
7363 }
7364
7365 /*-----------------------------------------------------------------*/
7366 /* genAnd  - code for and                                          */
7367 /*-----------------------------------------------------------------*/
7368 static void genAnd (iCode *ic, iCode *ifx)
7369 {
7370   operand *left, *right, *result;
7371   int size, offset=0;  
7372   unsigned long lit = 0L;
7373   int bytelit = 0;
7374   resolvedIfx rIfx;
7375
7376     FENTRY;
7377     
7378   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7379   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7380   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7381
7382   resolveIfx(&rIfx,ifx);
7383
7384   /* if left is a literal & right is not then exchange them */
7385   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7386       AOP_NEEDSACC(left)) {
7387     operand *tmp = right ;
7388     right = left;
7389     left = tmp;
7390   }
7391
7392   /* if result = right then exchange them */
7393   if(pic16_sameRegs(AOP(result),AOP(right))){
7394     operand *tmp = right ;
7395     right = left;
7396     left = tmp;
7397   }
7398
7399   /* if right is bit then exchange them */
7400   if (AOP_TYPE(right) == AOP_CRY &&
7401       AOP_TYPE(left) != AOP_CRY){
7402     operand *tmp = right ;
7403     right = left;
7404     left = tmp;
7405   }
7406   if(AOP_TYPE(right) == AOP_LIT)
7407     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7408
7409   size = AOP_SIZE(result);
7410
7411   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7412
7413   // if(bit & yy)
7414   // result = bit & yy;
7415   if (AOP_TYPE(left) == AOP_CRY){
7416     // c = bit & literal;
7417     if(AOP_TYPE(right) == AOP_LIT){
7418       if(lit & 1) {
7419         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7420           // no change
7421           goto release;
7422         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7423       } else {
7424         // bit(result) = 0;
7425         if(size && (AOP_TYPE(result) == AOP_CRY)){
7426           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7427           goto release;
7428         }
7429         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7430           jumpIfTrue(ifx);
7431           goto release;
7432         }
7433         pic16_emitcode("clr","c");
7434       }
7435     } else {
7436       if (AOP_TYPE(right) == AOP_CRY){
7437         // c = bit & bit;
7438         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7439         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7440       } else {
7441         // c = bit & val;
7442         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7443         // c = lsb
7444         pic16_emitcode("rrc","a");
7445         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7446       }
7447     }
7448     // bit = c
7449     // val = c
7450     if(size)
7451       pic16_outBitC(result);
7452     // if(bit & ...)
7453     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7454       genIfxJump(ifx, "c");           
7455     goto release ;
7456   }
7457
7458   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7459   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7460   if((AOP_TYPE(right) == AOP_LIT) &&
7461      (AOP_TYPE(result) == AOP_CRY) &&
7462      (AOP_TYPE(left) != AOP_CRY)){
7463     int posbit = isLiteralBit(lit);
7464     /* left &  2^n */
7465     if(posbit){
7466       posbit--;
7467       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7468       // bit = left & 2^n
7469       if(size)
7470         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7471       // if(left &  2^n)
7472       else{
7473         if(ifx){
7474 /*
7475           if(IC_TRUE(ifx)) {
7476             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7477             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7478           } else {
7479             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7480             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7481           }
7482 */
7483         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7484         size = AOP_SIZE(left);
7485
7486         {
7487           int bp = posbit, ofs=0;
7488           
7489             while(bp > 7) {
7490               bp -= 8;
7491               ofs++;
7492             }
7493
7494           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7495                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7496
7497         }
7498 /*
7499           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7500                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7501 */
7502           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7503           
7504           ifx->generated = 1;
7505         }
7506         goto release;
7507       }
7508     } else {
7509       symbol *tlbl = newiTempLabel(NULL);
7510       int sizel = AOP_SIZE(left);
7511
7512       if(size)
7513         emitSETC;
7514
7515       while(sizel--) {
7516         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7517
7518           /* patch provided by Aaron Colwell */
7519           if((posbit = isLiteralBit(bytelit)) != 0) {
7520               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7521                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7522                                                 (posbit-1),0, PO_GPR_REGISTER));
7523
7524               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7525 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7526           } else {
7527               if (bytelit == 0xff) {
7528                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7529                    * a peephole could optimize it out -- VR */
7530                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7531               } else {
7532                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7533                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7534               }
7535
7536               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7537                             pic16_popGetLabel(tlbl->key));
7538           }
7539         
7540 #if 0
7541           /* old code, left here for reference -- VR 09/2004 */
7542           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7543           // byte ==  2^n ?
7544           if((posbit = isLiteralBit(bytelit)) != 0)
7545             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7546           else{
7547             if(bytelit != 0x0FFL)
7548               pic16_emitcode("anl","a,%s",
7549                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7550             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7551           }
7552 #endif
7553         }
7554         offset++;
7555       }
7556       // bit = left & literal
7557       if(size) {
7558         emitCLRC;
7559         pic16_emitpLabel(tlbl->key);
7560       }
7561       // if(left & literal)
7562       else {
7563         if(ifx) {
7564           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7565           ifx->generated = 1;
7566         }
7567         pic16_emitpLabel(tlbl->key);
7568         goto release;
7569       }
7570     }
7571
7572     pic16_outBitC(result);
7573     goto release ;
7574   }
7575
7576   /* if left is same as result */
7577   if(pic16_sameRegs(AOP(result),AOP(left))){
7578     int know_W = -1;
7579     for(;size--; offset++,lit>>=8) {
7580       if(AOP_TYPE(right) == AOP_LIT){
7581         switch(lit & 0xff) {
7582         case 0x00:
7583           /*  and'ing with 0 has clears the result */
7584 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7585           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7586           break;
7587         case 0xff:
7588           /* and'ing with 0xff is a nop when the result and left are the same */
7589           break;
7590
7591         default:
7592           {
7593             int p = pic16_my_powof2( (~lit) & 0xff );
7594             if(p>=0) {
7595               /* only one bit is set in the literal, so use a bcf instruction */
7596 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7597               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7598
7599             } else {
7600               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7601               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7602               if(know_W != (lit&0xff))
7603                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7604               know_W = lit &0xff;
7605               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7606             }
7607           }    
7608         }
7609       } else {
7610         if (AOP_TYPE(left) == AOP_ACC) {
7611           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7612         } else {                    
7613           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7614           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7615
7616         }
7617       }
7618     }
7619
7620   } else {
7621     // left & result in different registers
7622     if(AOP_TYPE(result) == AOP_CRY){
7623       // result = bit
7624       // if(size), result in bit
7625       // if(!size && ifx), conditional oper: if(left & right)
7626       symbol *tlbl = newiTempLabel(NULL);
7627       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7628       if(size)
7629         pic16_emitcode("setb","c");
7630       while(sizer--){
7631         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7632         pic16_emitcode("anl","a,%s",
7633                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7634         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7635         offset++;
7636       }
7637       if(size){
7638         CLRC;
7639         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7640         pic16_outBitC(result);
7641       } else if(ifx)
7642         jmpTrueOrFalse(ifx, tlbl);
7643     } else {
7644       for(;(size--);offset++) {
7645         // normal case
7646         // result = left & right
7647         if(AOP_TYPE(right) == AOP_LIT){
7648           int t = (lit >> (offset*8)) & 0x0FFL;
7649           switch(t) { 
7650           case 0x00:
7651             pic16_emitcode("clrf","%s",
7652                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7653             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7654             break;
7655           case 0xff:
7656             pic16_emitcode("movf","%s,w",
7657                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7658             pic16_emitcode("movwf","%s",
7659                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7660             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7661             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7662             break;
7663           default:
7664             pic16_emitcode("movlw","0x%x",t);
7665             pic16_emitcode("andwf","%s,w",
7666                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7667             pic16_emitcode("movwf","%s",
7668                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7669               
7670             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7671             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7672             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7673           }
7674           continue;
7675         }
7676
7677         if (AOP_TYPE(left) == AOP_ACC) {
7678           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7679           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7680         } else {
7681           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7682           pic16_emitcode("andwf","%s,w",
7683                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7684           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7685           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7686         }
7687         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7688         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7689       }
7690     }
7691   }
7692
7693   release :
7694     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7695   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7696   pic16_freeAsmop(result,NULL,ic,TRUE);     
7697 }
7698
7699 /*-----------------------------------------------------------------*/
7700 /* genOr  - code for or                                            */
7701 /*-----------------------------------------------------------------*/
7702 static void genOr (iCode *ic, iCode *ifx)
7703 {
7704     operand *left, *right, *result;
7705     int size, offset=0;
7706     unsigned long lit = 0L;
7707
7708     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7709
7710     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7711     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7712     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7713
7714     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7715
7716     /* if left is a literal & right is not then exchange them */
7717     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7718         AOP_NEEDSACC(left)) {
7719         operand *tmp = right ;
7720         right = left;
7721         left = tmp;
7722     }
7723
7724     /* if result = right then exchange them */
7725     if(pic16_sameRegs(AOP(result),AOP(right))){
7726         operand *tmp = right ;
7727         right = left;
7728         left = tmp;
7729     }
7730
7731     /* if right is bit then exchange them */
7732     if (AOP_TYPE(right) == AOP_CRY &&
7733         AOP_TYPE(left) != AOP_CRY){
7734         operand *tmp = right ;
7735         right = left;
7736         left = tmp;
7737     }
7738
7739     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7740
7741     if(AOP_TYPE(right) == AOP_LIT)
7742         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7743
7744     size = AOP_SIZE(result);
7745
7746     // if(bit | yy)
7747     // xx = bit | yy;
7748     if (AOP_TYPE(left) == AOP_CRY){
7749         if(AOP_TYPE(right) == AOP_LIT){
7750             // c = bit & literal;
7751             if(lit){
7752                 // lit != 0 => result = 1
7753                 if(AOP_TYPE(result) == AOP_CRY){
7754                   if(size)
7755                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7756                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7757                   //     AOP(result)->aopu.aop_dir,
7758                   //     AOP(result)->aopu.aop_dir);
7759                     else if(ifx)
7760                         continueIfTrue(ifx);
7761                     goto release;
7762                 }
7763             } else {
7764                 // lit == 0 => result = left
7765                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7766                     goto release;
7767                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7768             }
7769         } else {
7770             if (AOP_TYPE(right) == AOP_CRY){
7771               if(pic16_sameRegs(AOP(result),AOP(left))){
7772                 // c = bit | bit;
7773                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7774                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7775                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7776
7777                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7778                          AOP(result)->aopu.aop_dir,
7779                          AOP(result)->aopu.aop_dir);
7780                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7781                          AOP(right)->aopu.aop_dir,
7782                          AOP(right)->aopu.aop_dir);
7783                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7784                          AOP(result)->aopu.aop_dir,
7785                          AOP(result)->aopu.aop_dir);
7786               } else {
7787                 if( AOP_TYPE(result) == AOP_ACC) {
7788                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7789                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7790                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7791                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7792
7793                 } else {
7794
7795                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7796                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7797                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7798                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7799
7800                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7801                                  AOP(result)->aopu.aop_dir,
7802                                  AOP(result)->aopu.aop_dir);
7803                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7804                                  AOP(right)->aopu.aop_dir,
7805                                  AOP(right)->aopu.aop_dir);
7806                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7807                                  AOP(left)->aopu.aop_dir,
7808                                  AOP(left)->aopu.aop_dir);
7809                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7810                                  AOP(result)->aopu.aop_dir,
7811                                  AOP(result)->aopu.aop_dir);
7812                 }
7813               }
7814             } else {
7815                 // c = bit | val;
7816                 symbol *tlbl = newiTempLabel(NULL);
7817                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7818
7819
7820                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7821                 if( AOP_TYPE(right) == AOP_ACC) {
7822                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7823                   emitSKPNZ;
7824                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7825                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7826                 }
7827
7828
7829
7830                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7831                     pic16_emitcode(";XXX setb","c");
7832                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7833                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7834                 pic16_toBoolean(right);
7835                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7836                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7837                     jmpTrueOrFalse(ifx, tlbl);
7838                     goto release;
7839                 } else {
7840                     CLRC;
7841                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7842                 }
7843             }
7844         }
7845         // bit = c
7846         // val = c
7847         if(size)
7848             pic16_outBitC(result);
7849         // if(bit | ...)
7850         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7851             genIfxJump(ifx, "c");           
7852         goto release ;
7853     }
7854
7855     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7856     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7857     if((AOP_TYPE(right) == AOP_LIT) &&
7858        (AOP_TYPE(result) == AOP_CRY) &&
7859        (AOP_TYPE(left) != AOP_CRY)){
7860         if(lit){
7861           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7862             // result = 1
7863             if(size)
7864                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7865             else 
7866                 continueIfTrue(ifx);
7867             goto release;
7868         } else {
7869           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7870             // lit = 0, result = boolean(left)
7871             if(size)
7872                 pic16_emitcode(";XXX setb","c");
7873             pic16_toBoolean(right);
7874             if(size){
7875                 symbol *tlbl = newiTempLabel(NULL);
7876                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7877                 CLRC;
7878                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7879             } else {
7880                 genIfxJump (ifx,"a");
7881                 goto release;
7882             }
7883         }
7884         pic16_outBitC(result);
7885         goto release ;
7886     }
7887
7888     /* if left is same as result */
7889     if(pic16_sameRegs(AOP(result),AOP(left))){
7890       int know_W = -1;
7891       for(;size--; offset++,lit>>=8) {
7892         if(AOP_TYPE(right) == AOP_LIT){
7893           if((lit & 0xff) == 0)
7894             /*  or'ing with 0 has no effect */
7895             continue;
7896           else {
7897             int p = pic16_my_powof2(lit & 0xff);
7898             if(p>=0) {
7899               /* only one bit is set in the literal, so use a bsf instruction */
7900               pic16_emitpcode(POC_BSF,
7901                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7902             } else {
7903               if(know_W != (lit & 0xff))
7904                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7905               know_W = lit & 0xff;
7906               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7907             }
7908                     
7909           }
7910         } else {
7911           if (AOP_TYPE(left) == AOP_ACC) {
7912             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7913 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914           } else {                  
7915             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7916             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7917
7918 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7920
7921           }
7922         }
7923       }
7924     } else {
7925         // left & result in different registers
7926         if(AOP_TYPE(result) == AOP_CRY){
7927             // result = bit
7928             // if(size), result in bit
7929             // if(!size && ifx), conditional oper: if(left | right)
7930             symbol *tlbl = newiTempLabel(NULL);
7931             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7932             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7933
7934
7935             if(size)
7936                 pic16_emitcode(";XXX setb","c");
7937             while(sizer--){
7938                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7939                 pic16_emitcode(";XXX orl","a,%s",
7940                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7941                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7942                 offset++;
7943             }
7944             if(size){
7945                 CLRC;
7946                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7947                 pic16_outBitC(result);
7948             } else if(ifx)
7949                 jmpTrueOrFalse(ifx, tlbl);
7950         } else for(;(size--);offset++){
7951           // normal case
7952           // result = left & right
7953           if(AOP_TYPE(right) == AOP_LIT){
7954             int t = (lit >> (offset*8)) & 0x0FFL;
7955             switch(t) { 
7956             case 0x00:
7957               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7958               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7959
7960 //            pic16_emitcode("movf","%s,w",
7961 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7962 //            pic16_emitcode("movwf","%s",
7963 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7964               break;
7965             default:
7966               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7967               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7968               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7969
7970 //            pic16_emitcode("movlw","0x%x",t);
7971 //            pic16_emitcode("iorwf","%s,w",
7972 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7973 //            pic16_emitcode("movwf","%s",
7974 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7975               
7976             }
7977             continue;
7978           }
7979
7980           // faster than result <- left, anl result,right
7981           // and better if result is SFR
7982           if (AOP_TYPE(left) == AOP_ACC) {
7983             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7984 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7985           } else {
7986             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7987             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7988
7989 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7990 //          pic16_emitcode("iorwf","%s,w",
7991 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7992           }
7993           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7994 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7995         }
7996     }
7997
7998 release :
7999     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8000     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8001     pic16_freeAsmop(result,NULL,ic,TRUE);     
8002 }
8003
8004 /*-----------------------------------------------------------------*/
8005 /* genXor - code for xclusive or                                   */
8006 /*-----------------------------------------------------------------*/
8007 static void genXor (iCode *ic, iCode *ifx)
8008 {
8009   operand *left, *right, *result;
8010   int size, offset=0;
8011   unsigned long lit = 0L;
8012
8013   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8014
8015   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8016   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8017   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8018
8019   /* if left is a literal & right is not ||
8020      if left needs acc & right does not */
8021   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8022       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8023     operand *tmp = right ;
8024     right = left;
8025     left = tmp;
8026   }
8027
8028   /* if result = right then exchange them */
8029   if(pic16_sameRegs(AOP(result),AOP(right))){
8030     operand *tmp = right ;
8031     right = left;
8032     left = tmp;
8033   }
8034
8035   /* if right is bit then exchange them */
8036   if (AOP_TYPE(right) == AOP_CRY &&
8037       AOP_TYPE(left) != AOP_CRY){
8038     operand *tmp = right ;
8039     right = left;
8040     left = tmp;
8041   }
8042   if(AOP_TYPE(right) == AOP_LIT)
8043     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8044
8045   size = AOP_SIZE(result);
8046
8047   // if(bit ^ yy)
8048   // xx = bit ^ yy;
8049   if (AOP_TYPE(left) == AOP_CRY){
8050     if(AOP_TYPE(right) == AOP_LIT){
8051       // c = bit & literal;
8052       if(lit>>1){
8053         // lit>>1  != 0 => result = 1
8054         if(AOP_TYPE(result) == AOP_CRY){
8055           if(size)
8056             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8057             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8058           else if(ifx)
8059             continueIfTrue(ifx);
8060           goto release;
8061         }
8062         pic16_emitcode("setb","c");
8063       } else{
8064         // lit == (0 or 1)
8065         if(lit == 0){
8066           // lit == 0, result = left
8067           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8068             goto release;
8069           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8070         } else{
8071           // lit == 1, result = not(left)
8072           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8073             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8074             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8075             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8076             goto release;
8077           } else {
8078             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8079             pic16_emitcode("cpl","c");
8080           }
8081         }
8082       }
8083
8084     } else {
8085       // right != literal
8086       symbol *tlbl = newiTempLabel(NULL);
8087       if (AOP_TYPE(right) == AOP_CRY){
8088         // c = bit ^ bit;
8089         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8090       }
8091       else{
8092         int sizer = AOP_SIZE(right);
8093         // c = bit ^ val
8094         // if val>>1 != 0, result = 1
8095         pic16_emitcode("setb","c");
8096         while(sizer){
8097           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8098           if(sizer == 1)
8099             // test the msb of the lsb
8100             pic16_emitcode("anl","a,#0xfe");
8101           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8102           sizer--;
8103         }
8104         // val = (0,1)
8105         pic16_emitcode("rrc","a");
8106       }
8107       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8108       pic16_emitcode("cpl","c");
8109       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8110     }
8111     // bit = c
8112     // val = c
8113     if(size)
8114       pic16_outBitC(result);
8115     // if(bit | ...)
8116     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8117       genIfxJump(ifx, "c");           
8118     goto release ;
8119   }
8120
8121   if(pic16_sameRegs(AOP(result),AOP(left))){
8122     /* if left is same as result */
8123     for(;size--; offset++) {
8124       if(AOP_TYPE(right) == AOP_LIT){
8125         int t  = (lit >> (offset*8)) & 0x0FFL;
8126         if(t == 0x00L)
8127           continue;
8128         else
8129           if (IS_AOP_PREG(left)) {
8130             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8131             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132             pic16_aopPut(AOP(result),"a",offset);
8133           } else {
8134             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8135             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8136             pic16_emitcode("xrl","%s,%s",
8137                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8138                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8139           }
8140       } else {
8141         if (AOP_TYPE(left) == AOP_ACC)
8142           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8143         else {
8144           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8145           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8146 /*
8147           if (IS_AOP_PREG(left)) {
8148             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8149             pic16_aopPut(AOP(result),"a",offset);
8150           } else
8151             pic16_emitcode("xrl","%s,a",
8152                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8153 */
8154         }
8155       }
8156     }
8157   } else {
8158     // left & result in different registers
8159     if(AOP_TYPE(result) == AOP_CRY){
8160       // result = bit
8161       // if(size), result in bit
8162       // if(!size && ifx), conditional oper: if(left ^ right)
8163       symbol *tlbl = newiTempLabel(NULL);
8164       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8165       if(size)
8166         pic16_emitcode("setb","c");
8167       while(sizer--){
8168         if((AOP_TYPE(right) == AOP_LIT) &&
8169            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8170           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8171         } else {
8172           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8173           pic16_emitcode("xrl","a,%s",
8174                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8175         }
8176         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8177         offset++;
8178       }
8179       if(size){
8180         CLRC;
8181         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8182         pic16_outBitC(result);
8183       } else if(ifx)
8184         jmpTrueOrFalse(ifx, tlbl);
8185     } else for(;(size--);offset++){
8186       // normal case
8187       // result = left & right
8188       if(AOP_TYPE(right) == AOP_LIT){
8189         int t = (lit >> (offset*8)) & 0x0FFL;
8190         switch(t) { 
8191         case 0x00:
8192           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8193           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8194           pic16_emitcode("movf","%s,w",
8195                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8196           pic16_emitcode("movwf","%s",
8197                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8198           break;
8199         case 0xff:
8200           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8201           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8202           pic16_emitcode("comf","%s,w",
8203                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8204           pic16_emitcode("movwf","%s",
8205                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8206           break;
8207         default:
8208           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8209           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8210           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8211           pic16_emitcode("movlw","0x%x",t);
8212           pic16_emitcode("xorwf","%s,w",
8213                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8214           pic16_emitcode("movwf","%s",
8215                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8216
8217         }
8218         continue;
8219       }
8220
8221       // faster than result <- left, anl result,right
8222       // and better if result is SFR
8223       if (AOP_TYPE(left) == AOP_ACC) {
8224         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8225         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8226       } else {
8227         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8228         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8229         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8230         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8231       }
8232       if ( AOP_TYPE(result) != AOP_ACC){
8233         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8234         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8235       }
8236     }
8237   }
8238
8239   release :
8240     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8241   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8242   pic16_freeAsmop(result,NULL,ic,TRUE);     
8243 }
8244
8245 /*-----------------------------------------------------------------*/
8246 /* genInline - write the inline code out                           */
8247 /*-----------------------------------------------------------------*/
8248 static void genInline (iCode *ic)
8249 {
8250   char *buffer, *bp, *bp1;
8251     
8252         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8253
8254         _G.inLine += (!options.asmpeep);
8255
8256         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8257         strcpy(buffer,IC_INLINE(ic));
8258         
8259         while((bp1=strstr(bp, "\\n"))) {
8260           *bp1++ = '\n';
8261           *bp1++ = ' ';
8262           bp = bp1;
8263         }
8264         bp = bp1 = buffer;
8265
8266 #if 0
8267   /* This is an experimental code for #pragma inline
8268      and is temporarily disabled for 2.5.0 release */
8269         if(asmInlineMap)
8270         {
8271           symbol *sym;
8272           char *s;
8273           char *cbuf;
8274           int cblen;
8275
8276             cbuf = Safe_strdup(buffer);
8277             cblen = strlen(buffer)+1;
8278             memset(cbuf, 0, cblen);
8279
8280             bp = buffer;
8281             bp1 = cbuf;
8282             while(*bp) {
8283               if(*bp != '%')*bp1++ = *bp++;
8284               else {
8285                 int i;
8286
8287                   bp++;
8288                   i = *bp - '0';
8289                   if(i>elementsInSet(asmInlineMap))break;
8290                   
8291                   bp++;
8292                   s = indexSet(asmInlineMap, i);
8293                   DEBUGpc("searching symbol s = `%s'", s);
8294                   sym = findSym(SymbolTab, NULL, s);
8295
8296                   if(sym->reqv) {
8297                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8298                   } else {
8299                     strcat(bp1, sym->rname);
8300                   }
8301                   
8302                   while(*bp1)bp1++;
8303               }
8304               
8305               if(strlen(bp1) > cblen - 16) {
8306                 int i = strlen(cbuf);
8307                 cblen += 50;
8308                 cbuf = realloc(cbuf, cblen);
8309                 memset(cbuf+i, 0, 50);
8310                 bp1 = cbuf + i;
8311               }
8312             }
8313             
8314             free(buffer);
8315             buffer = Safe_strdup( cbuf );
8316             free(cbuf);
8317             
8318             bp = bp1 = buffer;
8319         }
8320 #endif  /* 0 */
8321
8322         /* emit each line as a code */
8323         while (*bp) {
8324                 if (*bp == '\n') {
8325                         *bp++ = '\0';
8326
8327                         if(*bp1)
8328                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8329                         bp1 = bp;
8330                 } else {
8331                         if (*bp == ':') {
8332                                 bp++;
8333                                 *bp = '\0';
8334                                 bp++;
8335
8336                                 /* print label, use this special format with NULL directive
8337                                  * to denote that the argument should not be indented with tab */
8338                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8339                                 bp1 = bp;
8340                         } if (*bp == ';') {
8341                                 /* advance to end of line (prevent splitting of comments at ':' */
8342                                 while (*bp && *bp != '\n') {
8343                                         bp++;
8344                                 } // while
8345                         } else
8346                                 bp++;
8347                 }
8348         }
8349
8350         if ((bp1 != bp) && *bp1)
8351                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8352
8353
8354     Safe_free(buffer);
8355
8356     _G.inLine -= (!options.asmpeep);
8357 }
8358
8359 /*-----------------------------------------------------------------*/
8360 /* genRRC - rotate right with carry                                */
8361 /*-----------------------------------------------------------------*/
8362 static void genRRC (iCode *ic)
8363 {
8364   operand *left , *result ;
8365   int size, offset = 0, same;
8366
8367   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8368
8369   /* rotate right with carry */
8370   left = IC_LEFT(ic);
8371   result=IC_RESULT(ic);
8372   pic16_aopOp (left,ic,FALSE);
8373   pic16_aopOp (result,ic,TRUE);
8374
8375   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8376
8377   same = pic16_sameRegs(AOP(result),AOP(left));
8378
8379   size = AOP_SIZE(result);    
8380
8381   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8382
8383   /* get the lsb and put it into the carry */
8384   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8385
8386   offset = 0 ;
8387
8388   while(size--) {
8389
8390     if(same) {
8391       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8392     } else {
8393       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8394       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8395     }
8396
8397     offset++;
8398   }
8399
8400   pic16_freeAsmop(left,NULL,ic,TRUE);
8401   pic16_freeAsmop(result,NULL,ic,TRUE);
8402 }
8403
8404 /*-----------------------------------------------------------------*/
8405 /* genRLC - generate code for rotate left with carry               */
8406 /*-----------------------------------------------------------------*/
8407 static void genRLC (iCode *ic)
8408 {    
8409   operand *left , *result ;
8410   int size, offset = 0;
8411   int same;
8412
8413   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8414   /* rotate right with carry */
8415   left = IC_LEFT(ic);
8416   result=IC_RESULT(ic);
8417   pic16_aopOp (left,ic,FALSE);
8418   pic16_aopOp (result,ic,TRUE);
8419
8420   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8421
8422   same = pic16_sameRegs(AOP(result),AOP(left));
8423
8424   /* move it to the result */
8425   size = AOP_SIZE(result);    
8426
8427   /* get the msb and put it into the carry */
8428   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8429
8430   offset = 0 ;
8431
8432   while(size--) {
8433
8434     if(same) {
8435       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8436     } else {
8437       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8438       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8439     }
8440
8441     offset++;
8442   }
8443
8444
8445   pic16_freeAsmop(left,NULL,ic,TRUE);
8446   pic16_freeAsmop(result,NULL,ic,TRUE);
8447 }
8448
8449
8450 /* gpasm can get the highest order bit with HIGH/UPPER
8451  * so the following probably is not needed -- VR */
8452  
8453 /*-----------------------------------------------------------------*/
8454 /* genGetHbit - generates code get highest order bit               */
8455 /*-----------------------------------------------------------------*/
8456 static void genGetHbit (iCode *ic)
8457 {
8458     operand *left, *result;
8459     left = IC_LEFT(ic);
8460     result=IC_RESULT(ic);
8461     pic16_aopOp (left,ic,FALSE);
8462     pic16_aopOp (result,ic,FALSE);
8463
8464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8465     /* get the highest order byte into a */
8466     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8467     if(AOP_TYPE(result) == AOP_CRY){
8468         pic16_emitcode("rlc","a");
8469         pic16_outBitC(result);
8470     }
8471     else{
8472         pic16_emitcode("rl","a");
8473         pic16_emitcode("anl","a,#0x01");
8474         pic16_outAcc(result);
8475     }
8476
8477
8478     pic16_freeAsmop(left,NULL,ic,TRUE);
8479     pic16_freeAsmop(result,NULL,ic,TRUE);
8480 }
8481
8482 #if 0
8483 /*-----------------------------------------------------------------*/
8484 /* AccRol - rotate left accumulator by known count                 */
8485 /*-----------------------------------------------------------------*/
8486 static void AccRol (int shCount)
8487 {
8488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8489     shCount &= 0x0007;              // shCount : 0..7
8490     switch(shCount){
8491         case 0 :
8492             break;
8493         case 1 :
8494             pic16_emitcode("rl","a");
8495             break;
8496         case 2 :
8497             pic16_emitcode("rl","a");
8498             pic16_emitcode("rl","a");
8499             break;
8500         case 3 :
8501             pic16_emitcode("swap","a");
8502             pic16_emitcode("rr","a");
8503             break;
8504         case 4 :
8505             pic16_emitcode("swap","a");
8506             break;
8507         case 5 :
8508             pic16_emitcode("swap","a");
8509             pic16_emitcode("rl","a");
8510             break;
8511         case 6 :
8512             pic16_emitcode("rr","a");
8513             pic16_emitcode("rr","a");
8514             break;
8515         case 7 :
8516             pic16_emitcode("rr","a");
8517             break;
8518     }
8519 }
8520 #endif
8521
8522 /*-----------------------------------------------------------------*/
8523 /* AccLsh - left shift accumulator by known count                  */
8524 /*-----------------------------------------------------------------*/
8525 static void AccLsh (int shCount, int doMask)
8526 {
8527         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8528         switch(shCount){
8529                 case 0 :
8530                         return;
8531                         break;
8532                 case 1 :
8533                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8534                         break;
8535                 case 2 :
8536                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8537                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8538                         break;
8539                 case 3 :
8540                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8541                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8542                         break;
8543                 case 4 :
8544                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8545                         break;
8546                 case 5 :
8547                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8548                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         break;
8550                 case 6 :
8551                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         break;
8554                 case 7 :
8555                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         break;
8557         }
8558         if (doMask) {
8559                 /* no masking is required in genPackBits */
8560                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8561         }
8562 }
8563
8564 /*-----------------------------------------------------------------*/
8565 /* AccRsh - right shift accumulator by known count                 */
8566 /*-----------------------------------------------------------------*/
8567 static void AccRsh (int shCount, int andmask)
8568 {
8569         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8570         switch(shCount){
8571                 case 0 :
8572                         return; break;
8573                 case 1 :
8574                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575                         break;
8576                 case 2 :
8577                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8578                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579                         break;
8580                 case 3 :
8581                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8582                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8583                         break;
8584                 case 4 :
8585                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8586                         break;
8587                 case 5 :
8588                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8589                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8590                         break;
8591                 case 6 :
8592                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8593                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8594                         break;
8595                 case 7 :
8596                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8597                         break;
8598         }
8599         
8600         if(andmask)
8601                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8602         else
8603                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8604 }
8605
8606 #if 0
8607 /*-----------------------------------------------------------------*/
8608 /* AccSRsh - signed right shift accumulator by known count                 */
8609 /*-----------------------------------------------------------------*/
8610 static void AccSRsh (int shCount)
8611 {
8612     symbol *tlbl ;
8613     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8614     if(shCount != 0){
8615         if(shCount == 1){
8616             pic16_emitcode("mov","c,acc.7");
8617             pic16_emitcode("rrc","a");
8618         } else if(shCount == 2){
8619             pic16_emitcode("mov","c,acc.7");
8620             pic16_emitcode("rrc","a");
8621             pic16_emitcode("mov","c,acc.7");
8622             pic16_emitcode("rrc","a");
8623         } else {
8624             tlbl = newiTempLabel(NULL);
8625             /* rotate right accumulator */
8626             AccRol(8 - shCount);
8627             /* and kill the higher order bits */
8628             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8629             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8630             pic16_emitcode("orl","a,#0x%02x",
8631                      (unsigned char)~SRMask[shCount]);
8632             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8633         }
8634     }
8635 }
8636 #endif
8637
8638 /*-----------------------------------------------------------------*/
8639 /* shiftR1Left2Result - shift right one byte from left to result   */
8640 /*-----------------------------------------------------------------*/
8641 static void shiftR1Left2ResultSigned (operand *left, int offl,
8642                                 operand *result, int offr,
8643                                 int shCount)
8644 {
8645   int same;
8646
8647   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8648
8649   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8650
8651   switch(shCount) {
8652   case 1:
8653     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8654     if(same) 
8655       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8656     else {
8657       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8658       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8659     }
8660
8661     break;
8662   case 2:
8663
8664     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8665     if(same) 
8666       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8667     else {
8668       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8669       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8670     }
8671     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8672     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8673
8674     break;
8675
8676   case 3:
8677     if(same)
8678       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8679     else {
8680       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8681       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682     }
8683
8684     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8685     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8686     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8687
8688     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8689     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8690
8691     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8692     break;
8693
8694   case 4:
8695     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8696     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8697     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8698     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8699     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8700     break;
8701   case 5:
8702     if(same) {
8703       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8704     } else {
8705       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8706       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8707     }
8708     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8709     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8710     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8711     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8712     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8713     break;
8714
8715   case 6:
8716     if(same) {
8717       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8718       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8720       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8721       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8722       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8723     } else {
8724       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8725       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8726       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8727       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8728       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8729     }
8730     break;
8731
8732   case 7:
8733     if(same) {
8734       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8735       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8736       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8737       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8738     } else {
8739       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8740       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8741       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8742     }
8743
8744   default:
8745     break;
8746   }
8747 }
8748
8749 /*-----------------------------------------------------------------*/
8750 /* shiftR1Left2Result - shift right one byte from left to result   */
8751 /*-----------------------------------------------------------------*/
8752 static void shiftR1Left2Result (operand *left, int offl,
8753                                 operand *result, int offr,
8754                                 int shCount, int sign)
8755 {
8756   int same;
8757
8758   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8759
8760   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8761
8762   /* Copy the msb into the carry if signed. */
8763   if(sign) {
8764     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8765     return;
8766   }
8767
8768
8769
8770   switch(shCount) {
8771   case 1:
8772     emitCLRC;
8773     if(same) 
8774       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8775     else {
8776       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8777       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778     }
8779     break;
8780   case 2:
8781     emitCLRC;
8782     if(same) {
8783       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8784     } else {
8785       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8786       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787     }
8788     emitCLRC;
8789     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8790
8791     break;
8792   case 3:
8793     if(same)
8794       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8795     else {
8796       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8797       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8798     }
8799
8800     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8801     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8802     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8803     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8804     break;
8805       
8806   case 4:
8807     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8808     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8809     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8810     break;
8811
8812   case 5:
8813     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8814     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8815     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8816     //emitCLRC;
8817     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8818
8819     break;
8820   case 6:
8821
8822     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8823     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8824     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8825     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8826     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8827     break;
8828
8829   case 7:
8830
8831     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8832     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8833     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8834
8835     break;
8836
8837   default:
8838     break;
8839   }
8840 }
8841
8842 /*-----------------------------------------------------------------*/
8843 /* shiftL1Left2Result - shift left one byte from left to result    */
8844 /*-----------------------------------------------------------------*/
8845 static void shiftL1Left2Result (operand *left, int offl,
8846                                 operand *result, int offr, int shCount)
8847 {
8848   int same;
8849
8850   //    char *l;
8851   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8852
8853   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8854   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8855     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8856     //    MOVA(l);
8857     /* shift left accumulator */
8858     //AccLsh(shCount, 1); // don't comment out just yet...
8859   //    pic16_aopPut(AOP(result),"a",offr);
8860
8861   switch(shCount) {
8862   case 1:
8863     /* Shift left 1 bit position */
8864     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8865     if(same) {
8866       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8867     } else {
8868       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8869       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8870     }
8871     break;
8872   case 2:
8873     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8874     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8876     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8877     break;
8878   case 3:
8879     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8880     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8881     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8882     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8883     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8884     break;
8885   case 4:
8886     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8887     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8888     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8889     break;
8890   case 5:
8891     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8892     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8893     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8894     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8895     break;
8896   case 6:
8897     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8898     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8899     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8900     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8901     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8902     break;
8903   case 7:
8904     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8905     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8906     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8907     break;
8908
8909   default:
8910     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8911   }
8912
8913 }
8914
8915 /*-----------------------------------------------------------------*/
8916 /* movLeft2Result - move byte from left to result                  */
8917 /*-----------------------------------------------------------------*/
8918 static void movLeft2Result (operand *left, int offl,
8919                             operand *result, int offr)
8920 {
8921   char *l;
8922   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8923   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8924     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8925
8926     if (*l == '@' && (IS_AOP_PREG(result))) {
8927       pic16_emitcode("mov","a,%s",l);
8928       pic16_aopPut(AOP(result),"a",offr);
8929     } else {
8930       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8931       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8932     }
8933   }
8934 }
8935
8936 /*-----------------------------------------------------------------*/
8937 /* shiftL2Left2Result - shift left two bytes from left to result   */
8938 /*-----------------------------------------------------------------*/
8939 static void shiftL2Left2Result (operand *left, int offl,
8940                                 operand *result, int offr, int shCount)
8941 {
8942   int same = pic16_sameRegs(AOP(result), AOP(left));
8943   int i;
8944
8945   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8946
8947   if (same && (offl != offr)) { // shift bytes
8948     if (offr > offl) {
8949        for(i=1;i>-1;i--) {
8950          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8951          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8952        }
8953     } else { // just treat as different later on
8954                 same = 0;
8955     }
8956   }
8957
8958   if(same) {
8959     switch(shCount) {
8960     case 0:
8961       break;
8962     case 1:
8963     case 2:
8964     case 3:
8965
8966       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8969
8970       while(--shCount) {
8971                 emitCLRC;
8972                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8973                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8974       }
8975
8976       break;
8977     case 4:
8978     case 5:
8979       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8980       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8981       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8982       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8983       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8984       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8985       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8986       if(shCount >=5) {
8987                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8988                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8989       }
8990       break;
8991     case 6:
8992       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8993       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8994       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8995       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8996       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8997       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8998       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8999       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9000       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9001       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9002       break;
9003     case 7:
9004       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9005       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9006       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9007       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9008       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9009     }
9010
9011   } else {
9012     switch(shCount) {
9013     case 0:
9014       break;
9015     case 1:
9016     case 2:
9017     case 3:
9018       /* note, use a mov/add for the shift since the mov has a
9019          chance of getting optimized out */
9020       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9021       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9022       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9023       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025
9026       while(--shCount) {
9027                 emitCLRC;
9028                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9029                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9030       }
9031       break;
9032
9033     case 4:
9034     case 5:
9035       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9036       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9037       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9038       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9039       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9041       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9042       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9043
9044
9045       if(shCount == 5) {
9046                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9047                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9048       }
9049       break;
9050     case 6:
9051       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9052       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9053       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9054       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9055
9056       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9057       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9058       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9059       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9060       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9061       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9062       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9063       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9064       break;
9065     case 7:
9066       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9067       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9068       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9069       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9070       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9071     }
9072   }
9073
9074 }
9075 /*-----------------------------------------------------------------*/
9076 /* shiftR2Left2Result - shift right two bytes from left to result  */
9077 /*-----------------------------------------------------------------*/
9078 static void shiftR2Left2Result (operand *left, int offl,
9079                                 operand *result, int offr,
9080                                 int shCount, int sign)
9081 {
9082   int same = pic16_sameRegs(AOP(result), AOP(left));
9083   int i;
9084   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9085
9086   if (same && (offl != offr)) { // shift right bytes
9087     if (offr < offl) {
9088        for(i=0;i<2;i++) {
9089          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9090          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9091        }
9092     } else { // just treat as different later on
9093                 same = 0;
9094     }
9095   }
9096
9097   switch(shCount) {
9098   case 0:
9099     break;
9100   case 1:
9101   case 2:
9102   case 3:
9103     if(sign)
9104       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9105     else
9106       emitCLRC;
9107
9108     if(same) {
9109       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9110       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9111     } else {
9112       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9113       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9114       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9115       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116     }
9117
9118     while(--shCount) {
9119       if(sign)
9120                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9121       else
9122                 emitCLRC;
9123       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9124       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9125     }
9126     break;
9127   case 4:
9128   case 5:
9129     if(same) {
9130
9131       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9132       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9133       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9134
9135       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9136       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9137       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9138       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9139     } else {
9140       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9141       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9142       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9143
9144       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9145       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9146       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9147       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9148       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9149     }
9150
9151     if(shCount >=5) {
9152       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9153       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9154     }
9155
9156     if(sign) {
9157       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9158       pic16_emitpcode(POC_BTFSC, 
9159                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9160       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9161     }
9162
9163     break;
9164
9165   case 6:
9166     if(same) {
9167
9168       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9169       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9170
9171       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9172       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9173       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9174       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9175       if(sign) {
9176         pic16_emitpcode(POC_BTFSC, 
9177                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9178         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9179       }
9180       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9181       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9182       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9183       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9184     } else {
9185       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9186       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9187       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9188       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9189       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9190       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9191       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9192       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9193       if(sign) {
9194         pic16_emitpcode(POC_BTFSC, 
9195                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9196         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9197       }
9198       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9199       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9200
9201         
9202     }
9203
9204     break;
9205   case 7:
9206     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9207     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9208     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9209     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9210     if(sign) {
9211       emitSKPNC;
9212       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9213     } else 
9214       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9215   }
9216 }
9217
9218
9219 /*-----------------------------------------------------------------*/
9220 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9221 /*-----------------------------------------------------------------*/
9222 static void shiftLLeftOrResult (operand *left, int offl,
9223                                 operand *result, int offr, int shCount)
9224 {
9225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9226
9227     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9228     /* shift left accumulator */
9229     AccLsh(shCount, 1);
9230     /* or with result */
9231     /* back to result */
9232     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9233 }
9234
9235 /*-----------------------------------------------------------------*/
9236 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9237 /*-----------------------------------------------------------------*/
9238 static void shiftRLeftOrResult (operand *left, int offl,
9239                                 operand *result, int offr, int shCount)
9240 {
9241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9242     
9243     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9244     /* shift right accumulator */
9245     AccRsh(shCount, 1);
9246     /* or with result */
9247     /* back to result */
9248     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9249 }
9250
9251 /*-----------------------------------------------------------------*/
9252 /* genlshOne - left shift a one byte quantity by known count       */
9253 /*-----------------------------------------------------------------*/
9254 static void genlshOne (operand *result, operand *left, int shCount)
9255 {       
9256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9257     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9258 }
9259
9260 /*-----------------------------------------------------------------*/
9261 /* genlshTwo - left shift two bytes by known amount != 0           */
9262 /*-----------------------------------------------------------------*/
9263 static void genlshTwo (operand *result,operand *left, int shCount)
9264 {
9265     int size;
9266     
9267     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9268     size = pic16_getDataSize(result);
9269
9270     /* if shCount >= 8 */
9271     if (shCount >= 8) {
9272         shCount -= 8 ;
9273
9274         if (size > 1){
9275             if (shCount)
9276                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9277             else 
9278                 movLeft2Result(left, LSB, result, MSB16);
9279         }
9280         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9281     }
9282
9283     /*  1 <= shCount <= 7 */
9284     else {  
9285         if(size == 1)
9286             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9287         else 
9288             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9289     }
9290 }
9291
9292 /*-----------------------------------------------------------------*/
9293 /* shiftLLong - shift left one long from left to result            */
9294 /* offr = LSB or MSB16                                             */
9295 /*-----------------------------------------------------------------*/
9296 static void shiftLLong (operand *left, operand *result, int offr )
9297 {
9298     int size = AOP_SIZE(result);
9299     int same = pic16_sameRegs(AOP(left),AOP(result));
9300         int i;
9301
9302     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9303
9304         if (same && (offr == MSB16)) { //shift one byte
9305                 for(i=size-1;i>=MSB16;i--) {
9306                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9307                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9308                 }
9309         } else {
9310                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9311         }
9312         
9313     if (size > LSB+offr ){
9314                 if (same) {
9315                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9316                 } else {
9317                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9318                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9319                 }
9320          }
9321
9322     if(size > MSB16+offr){
9323                 if (same) {
9324                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9325                 } else {
9326                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9327                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9328                 }
9329     }
9330
9331     if(size > MSB24+offr){
9332                 if (same) {
9333                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9334                 } else {
9335                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9336                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9337                 }
9338     }
9339
9340     if(size > MSB32+offr){
9341                 if (same) {
9342                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9343                 } else {
9344                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9345                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9346                 }
9347     }
9348     if(offr != LSB)
9349                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9350
9351 }
9352
9353 /*-----------------------------------------------------------------*/
9354 /* genlshFour - shift four byte by a known amount != 0             */
9355 /*-----------------------------------------------------------------*/
9356 static void genlshFour (operand *result, operand *left, int shCount)
9357 {
9358     int size;
9359
9360     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9361     size = AOP_SIZE(result);
9362
9363     /* if shifting more that 3 bytes */
9364     if (shCount >= 24 ) {
9365         shCount -= 24;
9366         if (shCount)
9367             /* lowest order of left goes to the highest
9368             order of the destination */
9369             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9370         else
9371             movLeft2Result(left, LSB, result, MSB32);
9372
9373                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9374                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9375                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9376
9377         return;
9378     }
9379
9380     /* more than two bytes */
9381     else if ( shCount >= 16 ) {
9382         /* lower order two bytes goes to higher order two bytes */
9383         shCount -= 16;
9384         /* if some more remaining */
9385         if (shCount)
9386             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9387         else {
9388             movLeft2Result(left, MSB16, result, MSB32);
9389             movLeft2Result(left, LSB, result, MSB24);
9390         }
9391                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9392                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9393         return;
9394     }    
9395
9396     /* if more than 1 byte */
9397     else if ( shCount >= 8 ) {
9398         /* lower order three bytes goes to higher order  three bytes */
9399         shCount -= 8;
9400         if(size == 2){
9401             if(shCount)
9402                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9403             else
9404                 movLeft2Result(left, LSB, result, MSB16);
9405         }
9406         else{   /* size = 4 */
9407             if(shCount == 0){
9408                 movLeft2Result(left, MSB24, result, MSB32);
9409                 movLeft2Result(left, MSB16, result, MSB24);
9410                 movLeft2Result(left, LSB, result, MSB16);
9411                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9412             }
9413             else if(shCount == 1)
9414                 shiftLLong(left, result, MSB16);
9415             else{
9416                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9417                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9418                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9419                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9420             }
9421         }
9422     }
9423
9424     /* 1 <= shCount <= 7 */
9425     else if(shCount <= 3)
9426     { 
9427         shiftLLong(left, result, LSB);
9428         while(--shCount >= 1)
9429             shiftLLong(result, result, LSB);
9430     }
9431     /* 3 <= shCount <= 7, optimize */
9432     else{
9433         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9434         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9435         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9436     }
9437 }
9438
9439 /*-----------------------------------------------------------------*/
9440 /* genLeftShiftLiteral - left shifting by known count              */
9441 /*-----------------------------------------------------------------*/
9442 void pic16_genLeftShiftLiteral (operand *left,
9443                                  operand *right,
9444                                  operand *result,
9445                                  iCode *ic)
9446 {    
9447     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9448     int size;
9449
9450     FENTRY;
9451     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9452     pic16_freeAsmop(right,NULL,ic,TRUE);
9453
9454     pic16_aopOp(left,ic,FALSE);
9455     pic16_aopOp(result,ic,TRUE);
9456
9457     size = getSize(operandType(result));
9458
9459 #if VIEW_SIZE
9460     pic16_emitcode("; shift left ","result %d, left %d",size,
9461              AOP_SIZE(left));
9462 #endif
9463
9464     /* I suppose that the left size >= result size */
9465     if(shCount == 0){
9466         while(size--){
9467             movLeft2Result(left, size, result, size);
9468         }
9469     }
9470
9471     else if(shCount >= (size * 8))
9472         while(size--)
9473             pic16_aopPut(AOP(result),zero,size);
9474     else{
9475         switch (size) {
9476             case 1:
9477                 genlshOne (result,left,shCount);
9478                 break;
9479
9480             case 2:
9481             case 3:
9482                 genlshTwo (result,left,shCount);
9483                 break;
9484
9485             case 4:
9486                 genlshFour (result,left,shCount);
9487                 break;
9488         }
9489     }
9490     pic16_freeAsmop(left,NULL,ic,TRUE);
9491     pic16_freeAsmop(result,NULL,ic,TRUE);
9492 }
9493
9494 /*-----------------------------------------------------------------*
9495  * genMultiAsm - repeat assembly instruction for size of register.
9496  * if endian == 1, then the high byte (i.e base address + size of 
9497  * register) is used first else the low byte is used first;
9498  *-----------------------------------------------------------------*/
9499 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9500 {
9501
9502   int offset = 0;
9503
9504   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9505
9506   if(!reg)
9507     return;
9508
9509   if(!endian) {
9510     endian = 1;
9511   } else {
9512     endian = -1;
9513     offset = size-1;
9514   }
9515
9516   while(size--) {
9517     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9518     offset += endian;
9519   }
9520
9521 }
9522
9523 #if !(USE_GENERIC_SIGNED_SHIFT)
9524 /*-----------------------------------------------------------------*/
9525 /* genLeftShift - generates code for left shifting                 */
9526 /*-----------------------------------------------------------------*/
9527 static void genLeftShift (iCode *ic)
9528 {
9529   operand *left,*right, *result;
9530   int size, offset;
9531 //  char *l;
9532   symbol *tlbl , *tlbl1;
9533   pCodeOp *pctemp;
9534
9535   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9536
9537   right = IC_RIGHT(ic);
9538   left  = IC_LEFT(ic);
9539   result = IC_RESULT(ic);
9540
9541   pic16_aopOp(right,ic,FALSE);
9542
9543   /* if the shift count is known then do it 
9544      as efficiently as possible */
9545   if (AOP_TYPE(right) == AOP_LIT) {
9546     pic16_genLeftShiftLiteral (left,right,result,ic);
9547     return ;
9548   }
9549
9550   /* shift count is unknown then we have to form
9551    * a loop. Get the loop count in WREG : Note: we take
9552    * only the lower order byte since shifting
9553    * more than 32 bits make no sense anyway, ( the
9554    * largest size of an object can be only 32 bits ) */
9555   
9556   pic16_aopOp(left,ic,FALSE);
9557   pic16_aopOp(result,ic,FALSE);
9558
9559   /* now move the left to the result if they are not the
9560    * same, and if size > 1,
9561    * and if right is not same to result (!!!) -- VR */
9562   if (!pic16_sameRegs(AOP(left),AOP(result))
9563       && (AOP_SIZE(result) > 1)) {
9564
9565     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9566
9567     size = AOP_SIZE(result);
9568     offset=0;
9569     while (size--) {
9570
9571 #if 0
9572       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9573       if (*l == '@' && (IS_AOP_PREG(result))) {
9574
9575           pic16_emitcode("mov","a,%s",l);
9576           pic16_aopPut(AOP(result),"a",offset);
9577       } else
9578 #endif
9579       {
9580         /* we don't know if left is a literal or a register, take care -- VR */
9581         pic16_mov2f(AOP(result), AOP(left), offset);
9582       }
9583       offset++;
9584     }
9585   }
9586
9587   size = AOP_SIZE(result);
9588
9589   /* if it is only one byte then */
9590   if (size == 1) {
9591     if(optimized_for_speed) {
9592       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9593       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9594       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9595       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9596       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9597       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9598       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9599       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9600       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9601       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9602       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9603       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9604     } else {
9605
9606       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9607
9608       tlbl = newiTempLabel(NULL);
9609
9610 #if 1
9611       /* this is already done, why change it? */
9612       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9613                 pic16_mov2f(AOP(result), AOP(left), 0);
9614       }
9615 #endif
9616
9617       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9618       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9619       pic16_emitpLabel(tlbl->key);
9620       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9621       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9622       emitSKPC;
9623       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9624     }
9625     goto release ;
9626   }
9627     
9628   if (pic16_sameRegs(AOP(left),AOP(result))) {
9629
9630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9631     
9632     tlbl = newiTempLabel(NULL);
9633     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9634     genMultiAsm(POC_RRCF, result, size,1);
9635     pic16_emitpLabel(tlbl->key);
9636     genMultiAsm(POC_RLCF, result, size,0);
9637     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9638     emitSKPC;
9639     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9640     goto release;
9641   }
9642
9643   //tlbl = newiTempLabel(NULL);
9644   //offset = 0 ;   
9645   //tlbl1 = newiTempLabel(NULL);
9646
9647   //reAdjustPreg(AOP(result));    
9648     
9649   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9650   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9651   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9652   //MOVA(l);
9653   //pic16_emitcode("add","a,acc");         
9654   //pic16_aopPut(AOP(result),"a",offset++);
9655   //while (--size) {
9656   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9657   //  MOVA(l);
9658   //  pic16_emitcode("rlc","a");         
9659   //  pic16_aopPut(AOP(result),"a",offset++);
9660   //}
9661   //reAdjustPreg(AOP(result));
9662
9663   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9664   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9665
9666
9667   tlbl = newiTempLabel(NULL);
9668   tlbl1= newiTempLabel(NULL);
9669
9670   size = AOP_SIZE(result);
9671   offset = 1;
9672
9673   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9674
9675   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9676
9677   /* offset should be 0, 1 or 3 */
9678   
9679   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9680   emitSKPNZ;
9681   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9682
9683   pic16_emitpcode(POC_MOVWF, pctemp);
9684
9685
9686   pic16_emitpLabel(tlbl->key);
9687
9688   emitCLRC;
9689   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9690   while(--size)
9691     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9692
9693   pic16_emitpcode(POC_DECFSZ,  pctemp);
9694   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9695   pic16_emitpLabel(tlbl1->key);
9696
9697   pic16_popReleaseTempReg(pctemp,1);
9698
9699
9700  release:
9701   pic16_freeAsmop (right,NULL,ic,TRUE);
9702   pic16_freeAsmop(left,NULL,ic,TRUE);
9703   pic16_freeAsmop(result,NULL,ic,TRUE);
9704 }
9705 #endif
9706
9707
9708 #if 0
9709 #error old code (left here for reference)
9710 /*-----------------------------------------------------------------*/
9711 /* genLeftShift - generates code for left shifting                 */
9712 /*-----------------------------------------------------------------*/
9713 static void genLeftShift (iCode *ic)
9714 {
9715   operand *left,*right, *result;
9716   int size, offset;
9717   char *l;
9718   symbol *tlbl , *tlbl1;
9719   pCodeOp *pctemp;
9720
9721   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9722
9723   right = IC_RIGHT(ic);
9724   left  = IC_LEFT(ic);
9725   result = IC_RESULT(ic);
9726
9727   pic16_aopOp(right,ic,FALSE);
9728
9729   /* if the shift count is known then do it 
9730      as efficiently as possible */
9731   if (AOP_TYPE(right) == AOP_LIT) {
9732     pic16_genLeftShiftLiteral (left,right,result,ic);
9733     return ;
9734   }
9735
9736   /* shift count is unknown then we have to form 
9737      a loop get the loop count in B : Note: we take
9738      only the lower order byte since shifting
9739      more that 32 bits make no sense anyway, ( the
9740      largest size of an object can be only 32 bits ) */  
9741
9742     
9743   pic16_aopOp(left,ic,FALSE);
9744   pic16_aopOp(result,ic,FALSE);
9745
9746   /* now move the left to the result if they are not the
9747      same */
9748   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9749       AOP_SIZE(result) > 1) {
9750
9751     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9752
9753     size = AOP_SIZE(result);
9754     offset=0;
9755     while (size--) {
9756       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9757       if (*l == '@' && (IS_AOP_PREG(result))) {
9758
9759         pic16_emitcode("mov","a,%s",l);
9760         pic16_aopPut(AOP(result),"a",offset);
9761       } else {
9762
9763         /* we don't know if left is a literal or a register, take care -- VR */
9764         pic16_mov2f(AOP(result), AOP(left), offset);
9765       }
9766       offset++;
9767     }
9768   }
9769
9770   size = AOP_SIZE(result);
9771
9772   /* if it is only one byte then */
9773   if (size == 1) {
9774     if(optimized_for_speed) {
9775       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9776       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9777       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9778       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9779       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9780       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9781       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9782       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9783       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9784       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9785       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9786       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9787     } else {
9788
9789       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9790
9791       tlbl = newiTempLabel(NULL);
9792       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9793                 pic16_mov2f(AOP(result), AOP(left), 0);
9794                 
9795 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9796 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9797       }
9798
9799       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9800       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9801       pic16_emitpLabel(tlbl->key);
9802       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9803       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9804       emitSKPC;
9805       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9806     }
9807     goto release ;
9808   }
9809     
9810   if (pic16_sameRegs(AOP(left),AOP(result))) {
9811
9812     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9813     
9814     tlbl = newiTempLabel(NULL);
9815     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9816     genMultiAsm(POC_RRCF, result, size,1);
9817     pic16_emitpLabel(tlbl->key);
9818     genMultiAsm(POC_RLCF, result, size,0);
9819     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9820     emitSKPC;
9821     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9822     goto release;
9823   }
9824
9825   //tlbl = newiTempLabel(NULL);
9826   //offset = 0 ;   
9827   //tlbl1 = newiTempLabel(NULL);
9828
9829   //reAdjustPreg(AOP(result));    
9830     
9831   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9832   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9833   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9834   //MOVA(l);
9835   //pic16_emitcode("add","a,acc");         
9836   //pic16_aopPut(AOP(result),"a",offset++);
9837   //while (--size) {
9838   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9839   //  MOVA(l);
9840   //  pic16_emitcode("rlc","a");         
9841   //  pic16_aopPut(AOP(result),"a",offset++);
9842   //}
9843   //reAdjustPreg(AOP(result));
9844
9845   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9846   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9847
9848
9849   tlbl = newiTempLabel(NULL);
9850   tlbl1= newiTempLabel(NULL);
9851
9852   size = AOP_SIZE(result);
9853   offset = 1;
9854
9855   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9856
9857   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9858
9859   /* offset should be 0, 1 or 3 */
9860   
9861   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9862   emitSKPNZ;
9863   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9864
9865   pic16_emitpcode(POC_MOVWF, pctemp);
9866
9867
9868   pic16_emitpLabel(tlbl->key);
9869
9870   emitCLRC;
9871   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9872   while(--size)
9873     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9874
9875   pic16_emitpcode(POC_DECFSZ,  pctemp);
9876   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9877   pic16_emitpLabel(tlbl1->key);
9878
9879   pic16_popReleaseTempReg(pctemp,1);
9880
9881
9882  release:
9883   pic16_freeAsmop (right,NULL,ic,TRUE);
9884   pic16_freeAsmop(left,NULL,ic,TRUE);
9885   pic16_freeAsmop(result,NULL,ic,TRUE);
9886 }
9887 #endif
9888
9889 /*-----------------------------------------------------------------*/
9890 /* genrshOne - right shift a one byte quantity by known count      */
9891 /*-----------------------------------------------------------------*/
9892 static void genrshOne (operand *result, operand *left,
9893                        int shCount, int sign)
9894 {
9895     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9896     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9897 }
9898
9899 /*-----------------------------------------------------------------*/
9900 /* genrshTwo - right shift two bytes by known amount != 0          */
9901 /*-----------------------------------------------------------------*/
9902 static void genrshTwo (operand *result,operand *left,
9903                        int shCount, int sign)
9904 {
9905   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9906   /* if shCount >= 8 */
9907   if (shCount >= 8) {
9908     shCount -= 8 ;
9909     if (shCount)
9910       shiftR1Left2Result(left, MSB16, result, LSB,
9911                          shCount, sign);
9912     else
9913       movLeft2Result(left, MSB16, result, LSB);
9914
9915     pic16_addSign (result, 1, sign);
9916   }
9917
9918   /*  1 <= shCount <= 7 */
9919   else
9920     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9921 }
9922
9923 /*-----------------------------------------------------------------*/
9924 /* shiftRLong - shift right one long from left to result           */
9925 /* offl = LSB or MSB16                                             */
9926 /*-----------------------------------------------------------------*/
9927 static void shiftRLong (operand *left, int offl,
9928                         operand *result, int sign)
9929 {
9930     int size = AOP_SIZE(result);
9931     int same = pic16_sameRegs(AOP(left),AOP(result));
9932     int i;
9933     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9934
9935         if (same && (offl == MSB16)) { //shift one byte right
9936                 for(i=MSB16;i<size;i++) {
9937                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9938                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9939                 }
9940         }
9941
9942     if(sign)
9943                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9944         else
9945                 emitCLRC;
9946
9947         if (same) {
9948                 if (offl == LSB)
9949                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9950         } else {
9951         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9952         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9953         }
9954
9955     if(offl == MSB16) {
9956         /* add sign of "a" */
9957         pic16_addSign(result, MSB32, sign);
9958         }
9959
9960         if (same) {
9961         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9962         } else {
9963         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9964         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9965         }
9966         
9967         if (same) {
9968         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9969         } else {
9970         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9971         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9972         }
9973
9974         if (same) {
9975         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9976         } else {
9977         if(offl == LSB){
9978                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9979                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9980         }
9981         }
9982 }
9983
9984 /*-----------------------------------------------------------------*/
9985 /* genrshFour - shift four byte by a known amount != 0             */
9986 /*-----------------------------------------------------------------*/
9987 static void genrshFour (operand *result, operand *left,
9988                         int shCount, int sign)
9989 {
9990   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9991   /* if shifting more that 3 bytes */
9992   if(shCount >= 24 ) {
9993     shCount -= 24;
9994     if(shCount)
9995       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9996     else
9997       movLeft2Result(left, MSB32, result, LSB);
9998
9999     pic16_addSign(result, MSB16, sign);
10000   }
10001   else if(shCount >= 16){
10002     shCount -= 16;
10003     if(shCount)
10004       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10005     else{
10006       movLeft2Result(left, MSB24, result, LSB);
10007       movLeft2Result(left, MSB32, result, MSB16);
10008     }
10009     pic16_addSign(result, MSB24, sign);
10010   }
10011   else if(shCount >= 8){
10012     shCount -= 8;
10013     if(shCount == 1)
10014       shiftRLong(left, MSB16, result, sign);
10015     else if(shCount == 0){
10016       movLeft2Result(left, MSB16, result, LSB);
10017       movLeft2Result(left, MSB24, result, MSB16);
10018       movLeft2Result(left, MSB32, result, MSB24);
10019       pic16_addSign(result, MSB32, sign);
10020     }
10021     else{ //shcount >= 2
10022       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10023       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10024       /* the last shift is signed */
10025       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10026       pic16_addSign(result, MSB32, sign);
10027     }
10028   }
10029   else{   /* 1 <= shCount <= 7 */
10030     if(shCount <= 2){
10031       shiftRLong(left, LSB, result, sign);
10032       if(shCount == 2)
10033         shiftRLong(result, LSB, result, sign);
10034     }
10035     else{
10036       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10037       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10038       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10039     }
10040   }
10041 }
10042
10043 /*-----------------------------------------------------------------*/
10044 /* genRightShiftLiteral - right shifting by known count            */
10045 /*-----------------------------------------------------------------*/
10046 static void genRightShiftLiteral (operand *left,
10047                                   operand *right,
10048                                   operand *result,
10049                                   iCode *ic,
10050                                   int sign)
10051 {    
10052   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10053   int lsize,res_size;
10054
10055   pic16_freeAsmop(right,NULL,ic,TRUE);
10056
10057   pic16_aopOp(left,ic,FALSE);
10058   pic16_aopOp(result,ic,TRUE);
10059
10060   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10061
10062 #if VIEW_SIZE
10063   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10064                  AOP_SIZE(left));
10065 #endif
10066
10067   lsize = pic16_getDataSize(left);
10068   res_size = pic16_getDataSize(result);
10069   /* test the LEFT size !!! */
10070
10071   /* I suppose that the left size >= result size */
10072   if(shCount == 0){
10073     assert (res_size <= lsize);
10074     while (res_size--) {
10075       pic16_mov2f (AOP(result), AOP(left), res_size);
10076     } // for
10077   }
10078
10079   else if(shCount >= (lsize * 8)){
10080
10081     if(res_size == 1) {
10082       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10083       if(sign) {
10084         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10085         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10086       }
10087     } else {
10088
10089       if(sign) {
10090         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10091         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10092         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10093         while(res_size--)
10094           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10095
10096       } else {
10097
10098         while(res_size--)
10099           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10100       }
10101     }
10102   } else {
10103
10104     switch (res_size) {
10105     case 1:
10106       genrshOne (result,left,shCount,sign);
10107       break;
10108
10109     case 2:
10110       genrshTwo (result,left,shCount,sign);
10111       break;
10112
10113     case 4:
10114       genrshFour (result,left,shCount,sign);
10115       break;
10116     default :
10117       break;
10118     }
10119
10120   }
10121
10122   pic16_freeAsmop(left,NULL,ic,TRUE);
10123   pic16_freeAsmop(result,NULL,ic,TRUE);
10124 }
10125
10126 #if !(USE_GENERIC_SIGNED_SHIFT)
10127 /*-----------------------------------------------------------------*/
10128 /* genSignedRightShift - right shift of signed number              */
10129 /*-----------------------------------------------------------------*/
10130 static void genSignedRightShift (iCode *ic)
10131 {
10132   operand *right, *left, *result;
10133   int size, offset;
10134   //  char *l;
10135   symbol *tlbl, *tlbl1 ;
10136   pCodeOp *pctemp;
10137
10138   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10139
10140   /* we do it the hard way put the shift count in b
10141      and loop thru preserving the sign */
10142   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10143
10144   right = IC_RIGHT(ic);
10145   left  = IC_LEFT(ic);
10146   result = IC_RESULT(ic);
10147
10148   pic16_aopOp(right,ic,FALSE);  
10149   pic16_aopOp(left,ic,FALSE);
10150   pic16_aopOp(result,ic,FALSE);
10151
10152
10153   if ( AOP_TYPE(right) == AOP_LIT) {
10154     genRightShiftLiteral (left,right,result,ic,1);
10155     return ;
10156   }
10157   /* shift count is unknown then we have to form 
10158      a loop get the loop count in B : Note: we take
10159      only the lower order byte since shifting
10160      more that 32 bits make no sense anyway, ( the
10161      largest size of an object can be only 32 bits ) */  
10162
10163   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10164   //pic16_emitcode("inc","b");
10165   //pic16_freeAsmop (right,NULL,ic,TRUE);
10166   //pic16_aopOp(left,ic,FALSE);
10167   //pic16_aopOp(result,ic,FALSE);
10168
10169   /* now move the left to the result if they are not the
10170      same */
10171   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10172       AOP_SIZE(result) > 1) {
10173
10174     size = AOP_SIZE(result);
10175     offset=0;
10176     while (size--) { 
10177       /*
10178         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10179         if (*l == '@' && IS_AOP_PREG(result)) {
10180
10181         pic16_emitcode("mov","a,%s",l);
10182         pic16_aopPut(AOP(result),"a",offset);
10183         } else
10184         pic16_aopPut(AOP(result),l,offset);
10185       */
10186       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10187       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10188
10189       offset++;
10190     }
10191   }
10192
10193   /* mov the highest order bit to OVR */    
10194   tlbl = newiTempLabel(NULL);
10195   tlbl1= newiTempLabel(NULL);
10196
10197   size = AOP_SIZE(result);
10198   offset = size - 1;
10199
10200   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10201
10202   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10203
10204   /* offset should be 0, 1 or 3 */
10205   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10206   emitSKPNZ;
10207   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10208
10209   pic16_emitpcode(POC_MOVWF, pctemp);
10210
10211
10212   pic16_emitpLabel(tlbl->key);
10213
10214   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10215   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10216
10217   while(--size) {
10218     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10219   }
10220
10221   pic16_emitpcode(POC_DECFSZ,  pctemp);
10222   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10223   pic16_emitpLabel(tlbl1->key);
10224
10225   pic16_popReleaseTempReg(pctemp,1);
10226 #if 0
10227   size = AOP_SIZE(result);
10228   offset = size - 1;
10229   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10230   pic16_emitcode("rlc","a");
10231   pic16_emitcode("mov","ov,c");
10232   /* if it is only one byte then */
10233   if (size == 1) {
10234     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10235     MOVA(l);
10236     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10237     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10238     pic16_emitcode("mov","c,ov");
10239     pic16_emitcode("rrc","a");
10240     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10241     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10242     pic16_aopPut(AOP(result),"a",0);
10243     goto release ;
10244   }
10245
10246   reAdjustPreg(AOP(result));
10247   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10248   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10249   pic16_emitcode("mov","c,ov");
10250   while (size--) {
10251     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10252     MOVA(l);
10253     pic16_emitcode("rrc","a");         
10254     pic16_aopPut(AOP(result),"a",offset--);
10255   }
10256   reAdjustPreg(AOP(result));
10257   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10258   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10259
10260  release:
10261 #endif
10262
10263   pic16_freeAsmop(left,NULL,ic,TRUE);
10264   pic16_freeAsmop(result,NULL,ic,TRUE);
10265   pic16_freeAsmop(right,NULL,ic,TRUE);
10266 }
10267 #endif
10268
10269 #if !(USE_GENERIC_SIGNED_SHIFT)
10270 #warning This implementation of genRightShift() is incomplete!
10271 /*-----------------------------------------------------------------*/
10272 /* genRightShift - generate code for right shifting                */
10273 /*-----------------------------------------------------------------*/
10274 static void genRightShift (iCode *ic)
10275 {
10276     operand *right, *left, *result;
10277     sym_link *letype ;
10278     int size, offset;
10279     char *l;
10280     symbol *tlbl, *tlbl1 ;
10281
10282     /* if signed then we do it the hard way preserve the
10283     sign bit moving it inwards */
10284     letype = getSpec(operandType(IC_LEFT(ic)));
10285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10286
10287     if (!SPEC_USIGN(letype)) {
10288         genSignedRightShift (ic);
10289         return ;
10290     }
10291
10292     /* signed & unsigned types are treated the same : i.e. the
10293     signed is NOT propagated inwards : quoting from the
10294     ANSI - standard : "for E1 >> E2, is equivalent to division
10295     by 2**E2 if unsigned or if it has a non-negative value,
10296     otherwise the result is implementation defined ", MY definition
10297     is that the sign does not get propagated */
10298
10299     right = IC_RIGHT(ic);
10300     left  = IC_LEFT(ic);
10301     result = IC_RESULT(ic);
10302
10303     pic16_aopOp(right,ic,FALSE);
10304
10305     /* if the shift count is known then do it 
10306     as efficiently as possible */
10307     if (AOP_TYPE(right) == AOP_LIT) {
10308         genRightShiftLiteral (left,right,result,ic, 0);
10309         return ;
10310     }
10311
10312     /* shift count is unknown then we have to form 
10313     a loop get the loop count in B : Note: we take
10314     only the lower order byte since shifting
10315     more that 32 bits make no sense anyway, ( the
10316     largest size of an object can be only 32 bits ) */  
10317
10318     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10319     pic16_emitcode("inc","b");
10320     pic16_aopOp(left,ic,FALSE);
10321     pic16_aopOp(result,ic,FALSE);
10322
10323     /* now move the left to the result if they are not the
10324     same */
10325     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10326         AOP_SIZE(result) > 1) {
10327
10328         size = AOP_SIZE(result);
10329         offset=0;
10330         while (size--) {
10331             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10332             if (*l == '@' && IS_AOP_PREG(result)) {
10333
10334                 pic16_emitcode("mov","a,%s",l);
10335                 pic16_aopPut(AOP(result),"a",offset);
10336             } else
10337                 pic16_aopPut(AOP(result),l,offset);
10338             offset++;
10339         }
10340     }
10341
10342     tlbl = newiTempLabel(NULL);
10343     tlbl1= newiTempLabel(NULL);
10344     size = AOP_SIZE(result);
10345     offset = size - 1;
10346
10347     /* if it is only one byte then */
10348     if (size == 1) {
10349
10350       tlbl = newiTempLabel(NULL);
10351       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10352         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10353         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10354       }
10355
10356       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10357       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10358       pic16_emitpLabel(tlbl->key);
10359       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10360       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10361       emitSKPC;
10362       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10363
10364       goto release ;
10365     }
10366
10367     reAdjustPreg(AOP(result));
10368     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10369     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10370     CLRC;
10371     while (size--) {
10372         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10373         MOVA(l);
10374         pic16_emitcode("rrc","a");         
10375         pic16_aopPut(AOP(result),"a",offset--);
10376     }
10377     reAdjustPreg(AOP(result));
10378
10379     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10380     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10381
10382 release:
10383     pic16_freeAsmop(left,NULL,ic,TRUE);
10384     pic16_freeAsmop (right,NULL,ic,TRUE);
10385     pic16_freeAsmop(result,NULL,ic,TRUE);
10386 }
10387 #endif
10388
10389 #if (USE_GENERIC_SIGNED_SHIFT)
10390 /*-----------------------------------------------------------------*/
10391 /* genGenericShift - generates code for left or right shifting     */
10392 /*-----------------------------------------------------------------*/
10393 static void genGenericShift (iCode *ic, int isShiftLeft) {
10394   operand *left,*right, *result;
10395   int offset;
10396   int sign, signedCount;
10397   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10398   PIC_OPCODE pos_shift, neg_shift;
10399
10400   FENTRY;
10401
10402   right = IC_RIGHT(ic);
10403   left  = IC_LEFT(ic);
10404   result = IC_RESULT(ic);
10405
10406   pic16_aopOp(right,ic,FALSE);
10407   pic16_aopOp(left,ic,FALSE);
10408   pic16_aopOp(result,ic,TRUE);
10409
10410   sign = !SPEC_USIGN(operandType (left));
10411   signedCount = !SPEC_USIGN(operandType (right));
10412
10413   /* if the shift count is known then do it 
10414      as efficiently as possible */
10415   if (AOP_TYPE(right) == AOP_LIT) {
10416     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10417     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10418     // we should modify right->aopu.aop_lit here!
10419     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10420     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10421     if (isShiftLeft)
10422       pic16_genLeftShiftLiteral (left,right,result,ic);
10423     else
10424       genRightShiftLiteral (left,right,result,ic, sign);
10425
10426     goto release;
10427   } // if (right is literal)
10428
10429   /* shift count is unknown then we have to form a loop.
10430    * Note: we take only the lower order byte since shifting
10431    * more than 32 bits make no sense anyway, ( the
10432    * largest size of an object can be only 32 bits )
10433    * Note: we perform arithmetic shifts if the left operand is
10434    * signed and we do an (effective) right shift, i. e. we
10435    * shift in the sign bit from the left. */
10436    
10437   label_complete = newiTempLabel ( NULL );
10438   label_loop_pos = newiTempLabel ( NULL );
10439   label_loop_neg = NULL;
10440   label_negative = NULL;
10441   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10442   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10443
10444   if (signedCount) {
10445     // additional labels needed
10446     label_loop_neg = newiTempLabel ( NULL );
10447     label_negative = newiTempLabel ( NULL );
10448   } // if
10449
10450   // copy source to result -- this will effectively truncate the left operand to the size of result!
10451   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10452   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10453   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10454     pic16_mov2f (AOP(result),AOP(left), offset);
10455   } // for
10456
10457   // if result is longer than left, fill with zeros (or sign)
10458   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10459     if (sign && AOP_SIZE(left) > 0) {
10460       // shift signed operand -- fill with sign
10461       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10462       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10463       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10464       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10465         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10466       } // for
10467     } else {
10468       // shift unsigned operand -- fill result with zeros
10469       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10470         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10471       } // for
10472     }
10473   } // if (size mismatch)
10474
10475   pic16_mov2w (AOP(right), 0);
10476   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10477   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10478   
10479 #if 0
10480   // perform a shift by one (shift count is positive)
10481   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10482   // 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])
10483   pic16_emitpLabel (label_loop_pos->key);
10484   emitCLRC;
10485   if (sign && (pos_shift == POC_RRCF)) {
10486     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10487     emitSETC;
10488   } // if
10489   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10490   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10491   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10492 #else
10493   // perform a shift by one (shift count is positive)
10494   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10495   // 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])
10496   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10497   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10498   emitCLRC;
10499   pic16_emitpLabel (label_loop_pos->key);
10500   if (sign && (pos_shift == POC_RRCF)) {
10501     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10502     emitSETC;
10503   } // if
10504   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10505   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10506   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10507   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10508 #endif
10509
10510   if (signedCount) {
10511     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10512
10513     pic16_emitpLabel (label_negative->key);
10514     // perform a shift by -1 (shift count is negative)
10515     // 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)
10516     emitCLRC;
10517     pic16_emitpLabel (label_loop_neg->key);
10518     if (sign && (neg_shift == POC_RRCF)) {
10519       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10520       emitSETC;
10521     } // if
10522     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10523     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10524     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10525     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10526   } // if (signedCount)
10527
10528   pic16_emitpLabel (label_complete->key);
10529
10530 release:
10531   pic16_freeAsmop (right,NULL,ic,TRUE);
10532   pic16_freeAsmop(left,NULL,ic,TRUE);
10533   pic16_freeAsmop(result,NULL,ic,TRUE);
10534 }
10535
10536 static void genLeftShift (iCode *ic) {
10537   genGenericShift (ic, 1);
10538 }
10539
10540 static void genRightShift (iCode *ic) {
10541   genGenericShift (ic, 0);
10542 }
10543 #endif
10544
10545
10546 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10547 void pic16_loadFSR0(operand *op, int lit)
10548 {
10549   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10550     if (AOP_TYPE(op) == AOP_LIT) {
10551       /* handle 12 bit integers correctly */
10552       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10553       if ((val & 0x0fff) != val) {
10554         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10555                 val, (val & 0x0fff) );
10556         val &= 0x0fff;
10557       }
10558       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10559     } else {
10560       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10561     }
10562   } else {
10563     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10564     // set up FSR0 with address of result
10565     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10566     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10567   }
10568 }
10569
10570 /*----------------------------------------------------------------*/
10571 /* pic16_derefPtr - move one byte from the location ptr points to */
10572 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10573 /*                  to the location ptr points to (doWrite != 0)   */
10574 /*----------------------------------------------------------------*/
10575 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10576 {
10577   if (!IS_PTR(operandType(ptr)))
10578   {
10579     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10580     else pic16_mov2w (AOP(ptr), 0);
10581     return;
10582   }
10583
10584   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10585   /* We might determine pointer type right here: */
10586   p_type = DCL_TYPE(operandType(ptr));
10587
10588   switch (p_type) {
10589     case FPOINTER:
10590     case POINTER:
10591       if (!fsr0_setup || !*fsr0_setup)
10592       {
10593         pic16_loadFSR0( ptr, 0 );
10594         if (fsr0_setup) *fsr0_setup = 1;
10595       }
10596       if (doWrite)
10597         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10598       else
10599         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10600       break;
10601
10602     case GPOINTER:
10603       if (AOP(ptr)->aopu.aop_reg[2]) {
10604         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10605         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10606         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10607         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10608         pic16_mov2w(AOP(ptr), 2);
10609         pic16_callGenericPointerRW(doWrite, 1);
10610       } else {
10611         // data pointer (just 2 byte given)
10612         if (!fsr0_setup || !*fsr0_setup)
10613         {
10614           pic16_loadFSR0( ptr, 0 );
10615           if (fsr0_setup) *fsr0_setup = 1;
10616         }
10617         if (doWrite)
10618           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10619         else
10620           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10621       }
10622       break;
10623
10624     default:
10625       assert (0 && "invalid pointer type specified");
10626       break;
10627   }
10628 }
10629
10630 /*-----------------------------------------------------------------*/
10631 /* genUnpackBits - generates code for unpacking bits               */
10632 /*-----------------------------------------------------------------*/
10633 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10634 {    
10635   int shCnt ;
10636   sym_link *etype, *letype;
10637   int blen=0, bstr=0;
10638   int lbstr;
10639   int same;
10640   pCodeOp *op;
10641
10642   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10643   etype = getSpec(operandType(result));
10644   letype = getSpec(operandType(left));
10645
10646   //    if(IS_BITFIELD(etype)) {
10647   blen = SPEC_BLEN(etype);
10648   bstr = SPEC_BSTR(etype);
10649   //    }
10650
10651   lbstr = SPEC_BSTR( letype );
10652
10653   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10654       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10655
10656 #if 1
10657   if((blen == 1) && (bstr < 8)
10658       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10659     /* it is a single bit, so use the appropriate bit instructions */
10660     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10661
10662     same = pic16_sameRegs(AOP(left),AOP(result));
10663     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10664     pic16_emitpcode(POC_CLRF, op);
10665
10666     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10667       /* workaround to reduce the extra lfsr instruction */
10668       pic16_emitpcode(POC_BTFSC,
10669           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10670     } else {
10671       assert (PIC_IS_DATA_PTR (operandType(left)));
10672       pic16_loadFSR0 (left, 0);
10673       pic16_emitpcode(POC_BTFSC,
10674           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10675     }
10676
10677     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10678       /* unsigned bitfields result in either 0 or 1 */
10679       pic16_emitpcode(POC_INCF, op);
10680     } else {
10681       /* signed bitfields result in either 0 or -1 */
10682       pic16_emitpcode(POC_DECF, op);
10683     }
10684     if (same) {
10685       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10686     }
10687
10688     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10689     return;
10690   }
10691
10692 #endif
10693
10694   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10695     // access symbol directly
10696     pic16_mov2w (AOP(left), 0);
10697   } else {
10698     pic16_derefPtr (left, ptype, 0, NULL);
10699   }
10700
10701   /* if we have bitdisplacement then it fits   */
10702   /* into this byte completely or if length is */
10703   /* less than a byte                          */
10704   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10705
10706     /* shift right acc */
10707     AccRsh(shCnt, 0);
10708
10709     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10710           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10711
10712     /* VR -- normally I would use the following, but since we use the hack,
10713      * to avoid the masking from AccRsh, why not mask it right now? */
10714
10715     /*
10716        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10717      */
10718
10719     /* extend signed bitfields to 8 bits */
10720     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10721     {
10722       assert (blen + bstr > 0);
10723       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10724       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10725     }
10726
10727     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10728
10729     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10730     return ;
10731   }
10732
10733   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10734   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10735   exit(-1);
10736
10737   return ;
10738 }
10739
10740
10741 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10742 {
10743   int size, offset = 0, leoffset=0 ;
10744
10745         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10746         pic16_aopOp(result, ic, TRUE);
10747
10748         FENTRY;
10749
10750         size = AOP_SIZE(result);
10751 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10752
10753
10754 #if 1
10755         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10756                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10757                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10758                 goto release;
10759         }
10760 #endif
10761
10762         if(AOP(left)->aopu.pcop->type == PO_DIR)
10763                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10764
10765         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10766
10767         while (size--) {
10768                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10769                 
10770 //              pic16_DumpOp("(result)",result);
10771                 if(is_LitAOp(AOP(result))) {
10772                         pic16_mov2w(AOP(left), offset); // patch 8
10773                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10774                 } else {
10775                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10776                                 pic16_popGet(AOP(left), offset), //patch 8
10777                                 pic16_popGet(AOP(result), offset)));
10778                 }
10779
10780                 offset++;
10781                 leoffset++;
10782         }
10783
10784 release:
10785     pic16_freeAsmop(result,NULL,ic,TRUE);
10786 }
10787
10788
10789
10790 /*-----------------------------------------------------------------*/
10791 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10792 /*-----------------------------------------------------------------*/
10793 static void genNearPointerGet (operand *left, 
10794                                operand *result, 
10795                                iCode *ic)
10796 {
10797 //  asmop *aop = NULL;
10798   //regs *preg = NULL ;
10799   sym_link *rtype, *retype;
10800   sym_link *ltype, *letype;
10801
10802     FENTRY;
10803     
10804     rtype = operandType(result);
10805     retype= getSpec(rtype);
10806     ltype = operandType(left);
10807     letype= getSpec(ltype);
10808     
10809     pic16_aopOp(left,ic,FALSE);
10810
10811 //    pic16_DumpOp("(left)",left);
10812 //    pic16_DumpOp("(result)",result);
10813
10814     /* if left is rematerialisable and
10815      * result is not bit variable type and
10816      * the left is pointer to data space i.e
10817      * lower 128 bytes of space */
10818     
10819     if (AOP_TYPE(left) == AOP_PCODE
10820       && !IS_BITFIELD(retype)
10821       && DCL_TYPE(ltype) == POINTER) {
10822
10823         genDataPointerGet (left,result,ic);
10824         pic16_freeAsmop(left, NULL, ic, TRUE);
10825         return ;
10826     }
10827     
10828     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10829     pic16_aopOp (result,ic,TRUE);
10830     
10831     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10832
10833 #if 1
10834     if(IS_BITFIELD( retype )
10835       && (SPEC_BLEN(operandType(result))==1)
10836     ) {
10837       iCode *nextic;
10838       pCodeOp *jop;
10839       int bitstrt, bytestrt;
10840
10841         /* if this is bitfield of size 1, see if we are checking the value
10842          * of a single bit in an if-statement,
10843          * if yes, then don't generate usual code, but execute the
10844          * genIfx directly -- VR */
10845
10846         nextic = ic->next;
10847
10848         /* CHECK: if next iCode is IFX
10849          * and current result operand is nextic's conditional operand
10850          * and current result operand live ranges ends at nextic's key number
10851          */
10852         if((nextic->op == IFX)
10853           && (result == IC_COND(nextic))
10854           && (OP_LIVETO(result) == nextic->seq)
10855           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10856           ) {
10857             /* everything is ok then */
10858             /* find a way to optimize the genIfx iCode */
10859
10860             bytestrt = SPEC_BSTR(operandType(result))/8;
10861             bitstrt = SPEC_BSTR(operandType(result))%8;
10862             
10863             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10864
10865             genIfxpCOpJump(nextic, jop);
10866             
10867             pic16_freeAsmop(left, NULL, ic, TRUE);
10868             pic16_freeAsmop(result, NULL, ic, TRUE);
10869             return;
10870         }
10871     }
10872 #endif
10873
10874     /* if bitfield then unpack the bits */
10875     if (IS_BITFIELD(letype)) 
10876       genUnpackBits (result, left, NULL, POINTER);
10877     else {
10878       /* we have can just get the values */
10879       int size = AOP_SIZE(result);
10880       int offset = 0;   
10881         
10882       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10883
10884       pic16_loadFSR0( left, 0 );
10885
10886       while(size--) {
10887         if(size) {
10888           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10889                 pic16_popGet(AOP(result), offset++)));
10890         } else {
10891           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10892                 pic16_popGet(AOP(result), offset++)));
10893         }
10894       }
10895     }
10896
10897 #if 0
10898     /* now some housekeeping stuff */
10899     if (aop) {
10900       /* we had to allocate for this iCode */
10901       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10902       pic16_freeAsmop(NULL,aop,ic,TRUE);
10903     } else { 
10904       /* we did not allocate which means left
10905        * already in a pointer register, then
10906        * if size > 0 && this could be used again
10907        * we have to point it back to where it 
10908        * belongs */
10909       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10910       if (AOP_SIZE(result) > 1
10911         && !OP_SYMBOL(left)->remat
10912         && ( OP_SYMBOL(left)->liveTo > ic->seq
10913             || ic->depth )) {
10914 //        int size = AOP_SIZE(result) - 1;
10915 //        while (size--)
10916 //          pic16_emitcode("dec","%s",rname);
10917         }
10918     }
10919 #endif
10920
10921     /* done */
10922     pic16_freeAsmop(left,NULL,ic,TRUE);
10923     pic16_freeAsmop(result,NULL,ic,TRUE);
10924 }
10925
10926 /*-----------------------------------------------------------------*/
10927 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10928 /*-----------------------------------------------------------------*/
10929 static void genPagedPointerGet (operand *left, 
10930                                operand *result, 
10931                                iCode *ic)
10932 {
10933     asmop *aop = NULL;
10934     regs *preg = NULL ;
10935     char *rname ;
10936     sym_link *rtype, *retype;    
10937
10938     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10939
10940     rtype = operandType(result);
10941     retype= getSpec(rtype);
10942     
10943     pic16_aopOp(left,ic,FALSE);
10944
10945   /* if the value is already in a pointer register
10946        then don't need anything more */
10947     if (!AOP_INPREG(AOP(left))) {
10948         /* otherwise get a free pointer register */
10949         aop = newAsmop(0);
10950         preg = getFreePtr(ic,&aop,FALSE);
10951         pic16_emitcode("mov","%s,%s",
10952                 preg->name,
10953                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10954         rname = preg->name ;
10955     } else
10956         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10957     
10958     pic16_freeAsmop(left,NULL,ic,TRUE);
10959     pic16_aopOp (result,ic,TRUE);
10960
10961     /* if bitfield then unpack the bits */
10962     if (IS_BITFIELD(retype)) 
10963         genUnpackBits (result,left,rname,PPOINTER);
10964     else {
10965         /* we have can just get the values */
10966         int size = AOP_SIZE(result);
10967         int offset = 0 ;        
10968         
10969         while (size--) {
10970             
10971             pic16_emitcode("movx","a,@%s",rname);
10972             pic16_aopPut(AOP(result),"a",offset);
10973             
10974             offset++ ;
10975             
10976             if (size)
10977                 pic16_emitcode("inc","%s",rname);
10978         }
10979     }
10980
10981     /* now some housekeeping stuff */
10982     if (aop) {
10983         /* we had to allocate for this iCode */
10984         pic16_freeAsmop(NULL,aop,ic,TRUE);
10985     } else { 
10986         /* we did not allocate which means left
10987            already in a pointer register, then
10988            if size > 0 && this could be used again
10989            we have to point it back to where it 
10990            belongs */
10991         if (AOP_SIZE(result) > 1 &&
10992             !OP_SYMBOL(left)->remat &&
10993             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10994               ic->depth )) {
10995             int size = AOP_SIZE(result) - 1;
10996             while (size--)
10997                 pic16_emitcode("dec","%s",rname);
10998         }
10999     }
11000
11001     /* done */
11002     pic16_freeAsmop(result,NULL,ic,TRUE);
11003     
11004         
11005 }
11006
11007 #if 0
11008 /* This code is not adjusted to PIC16 and fails utterly.
11009  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11010
11011 /*-----------------------------------------------------------------*/
11012 /* genFarPointerGet - gget value from far space                    */
11013 /*-----------------------------------------------------------------*/
11014 static void genFarPointerGet (operand *left,
11015                               operand *result, iCode *ic)
11016 {
11017     int size, offset ;
11018     sym_link *retype = getSpec(operandType(result));
11019
11020     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11021
11022     pic16_aopOp(left,ic,FALSE);
11023
11024     /* if the operand is already in dptr 
11025     then we do nothing else we move the value to dptr */
11026     if (AOP_TYPE(left) != AOP_STR) {
11027         /* if this is remateriazable */
11028         if (AOP_TYPE(left) == AOP_IMMD)
11029             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11030         else { /* we need to get it byte by byte */
11031             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11032             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11033             if (options.model == MODEL_FLAT24)
11034             {
11035                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11036             }
11037         }
11038     }
11039     /* so dptr know contains the address */
11040     pic16_freeAsmop(left,NULL,ic,TRUE);
11041     pic16_aopOp(result,ic,TRUE);
11042
11043     /* if bit then unpack */
11044     if (IS_BITFIELD(retype)) 
11045         genUnpackBits(result,left,"dptr",FPOINTER);
11046     else {
11047         size = AOP_SIZE(result);
11048         offset = 0 ;
11049
11050         while (size--) {
11051             pic16_emitcode("movx","a,@dptr");
11052             pic16_aopPut(AOP(result),"a",offset++);
11053             if (size)
11054                 pic16_emitcode("inc","dptr");
11055         }
11056     }
11057
11058     pic16_freeAsmop(result,NULL,ic,TRUE);
11059 }
11060 #endif
11061
11062 #if 0
11063 /*-----------------------------------------------------------------*/
11064 /* genCodePointerGet - get value from code space                  */
11065 /*-----------------------------------------------------------------*/
11066 static void genCodePointerGet (operand *left,
11067                                 operand *result, iCode *ic)
11068 {
11069     int size, offset ;
11070     sym_link *retype = getSpec(operandType(result));
11071
11072     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11073
11074     pic16_aopOp(left,ic,FALSE);
11075
11076     /* if the operand is already in dptr 
11077     then we do nothing else we move the value to dptr */
11078     if (AOP_TYPE(left) != AOP_STR) {
11079         /* if this is remateriazable */
11080         if (AOP_TYPE(left) == AOP_IMMD)
11081             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11082         else { /* we need to get it byte by byte */
11083             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11084             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11085             if (options.model == MODEL_FLAT24)
11086             {
11087                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11088             }
11089         }
11090     }
11091     /* so dptr know contains the address */
11092     pic16_freeAsmop(left,NULL,ic,TRUE);
11093     pic16_aopOp(result,ic,FALSE);
11094
11095     /* if bit then unpack */
11096     if (IS_BITFIELD(retype)) 
11097         genUnpackBits(result,left,"dptr",CPOINTER);
11098     else {
11099         size = AOP_SIZE(result);
11100         offset = 0 ;
11101
11102         while (size--) {
11103             pic16_emitcode("clr","a");
11104             pic16_emitcode("movc","a,@a+dptr");
11105             pic16_aopPut(AOP(result),"a",offset++);
11106             if (size)
11107                 pic16_emitcode("inc","dptr");
11108         }
11109     }
11110
11111     pic16_freeAsmop(result,NULL,ic,TRUE);
11112 }
11113 #endif
11114
11115 #if 0
11116 /*-----------------------------------------------------------------*/
11117 /* genGenPointerGet - gget value from generic pointer space        */
11118 /*-----------------------------------------------------------------*/
11119 static void genGenPointerGet (operand *left,
11120                               operand *result, iCode *ic)
11121 {
11122   int size, offset, lit;
11123   sym_link *retype = getSpec(operandType(result));
11124
11125         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11126         pic16_aopOp(left,ic,FALSE);
11127         pic16_aopOp(result,ic,FALSE);
11128         size = AOP_SIZE(result);
11129
11130         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11131
11132         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11133
11134                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11135                 // load FSR0 from immediate
11136                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11137
11138 //              pic16_loadFSR0( left );
11139
11140                 offset = 0;
11141                 while(size--) {
11142                         if(size) {
11143                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11144                         } else {
11145                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11146                         }
11147                         offset++;
11148                 }
11149                 goto release;
11150
11151         }
11152         else { /* we need to get it byte by byte */
11153                 // set up FSR0 with address from left
11154                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11155                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11156                 
11157                 offset = 0 ;
11158
11159                 while(size--) {
11160                         if(size) {
11161                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11162                         } else {
11163                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11164                         }
11165                         offset++;
11166                 }
11167                 goto release;
11168         }
11169
11170   /* if bit then unpack */
11171         if (IS_BITFIELD(retype)) 
11172                 genUnpackBits(result,left,"BAD",GPOINTER);
11173
11174         release:
11175         pic16_freeAsmop(left,NULL,ic,TRUE);
11176         pic16_freeAsmop(result,NULL,ic,TRUE);
11177
11178 }
11179 #endif
11180
11181
11182 /*-----------------------------------------------------------------*/
11183 /* genGenPointerGet - gget value from generic pointer space        */
11184 /*-----------------------------------------------------------------*/
11185 static void genGenPointerGet (operand *left,
11186                               operand *result, iCode *ic)
11187 {
11188   int size, offset, lit;
11189   sym_link *letype = getSpec(operandType(left));
11190
11191     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11192     pic16_aopOp(left,ic,FALSE);
11193     pic16_aopOp(result,ic,TRUE);
11194     size = AOP_SIZE(result);
11195
11196     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11197   
11198     /* if bit then unpack */
11199     if (IS_BITFIELD(letype)) {
11200       genUnpackBits(result,left,"BAD",GPOINTER);
11201       goto release;
11202     }
11203
11204     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11205
11206       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11207       // load FSR0 from immediate
11208       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11209
11210       werror(W_POSSBUG2, __FILE__, __LINE__);
11211
11212       offset = 0;
11213       while(size--) {
11214         if(size) {
11215           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11216         } else {
11217           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11218         }
11219         offset++;
11220       }
11221
11222       goto release;
11223
11224     } else { /* we need to get it byte by byte */
11225
11226       /* set up WREG:PRODL:FSR0L with address from left */
11227       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11228       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11229       pic16_mov2w(AOP(left), 2);
11230       pic16_callGenericPointerRW(0, size);
11231       
11232       assignResultValue(result, 1);
11233       
11234       goto release;
11235     }
11236
11237 release:
11238   pic16_freeAsmop(left,NULL,ic,TRUE);
11239   pic16_freeAsmop(result,NULL,ic,TRUE);
11240 }
11241
11242 /*-----------------------------------------------------------------*/
11243 /* genConstPointerGet - get value from const generic pointer space */
11244 /*-----------------------------------------------------------------*/
11245 static void genConstPointerGet (operand *left,
11246                                 operand *result, iCode *ic)
11247 {
11248   //sym_link *retype = getSpec(operandType(result));
11249   // symbol *albl = newiTempLabel(NULL);        // patch 15
11250   // symbol *blbl = newiTempLabel(NULL);        //
11251   // PIC_OPCODE poc;                            // patch 15
11252   int size;
11253   int offset = 0;
11254
11255   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11256   pic16_aopOp(left,ic,FALSE);
11257   pic16_aopOp(result,ic,TRUE);
11258   size = AOP_SIZE(result);
11259
11260   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11261
11262   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11263
11264   // set up table pointer
11265   if( (AOP_TYPE(left) == AOP_PCODE) 
11266       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11267           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11268     {
11269       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11270       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11271       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11272       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11273       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11274       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11275   } else {
11276     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11277     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11278     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11279   }
11280
11281   while(size--) {
11282     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11283     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11284     offset++;
11285   }
11286     
11287   pic16_freeAsmop(left,NULL,ic,TRUE);
11288   pic16_freeAsmop(result,NULL,ic,TRUE);
11289 }
11290
11291
11292 /*-----------------------------------------------------------------*/
11293 /* genPointerGet - generate code for pointer get                   */
11294 /*-----------------------------------------------------------------*/
11295 static void genPointerGet (iCode *ic)
11296 {
11297   operand *left, *result ;
11298   sym_link *type, *etype;
11299   int p_type;
11300
11301     FENTRY;
11302     
11303     left = IC_LEFT(ic);
11304     result = IC_RESULT(ic) ;
11305
11306     /* depending on the type of pointer we need to
11307     move it to the correct pointer register */
11308     type = operandType(left);
11309     etype = getSpec(type);
11310
11311 #if 0
11312     if (IS_PTR_CONST(type))
11313 #else
11314     if (IS_CODEPTR(type))
11315 #endif
11316       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11317
11318     /* if left is of type of pointer then it is simple */
11319     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11320       p_type = DCL_TYPE(type);
11321     else {
11322       /* we have to go by the storage class */
11323       p_type = PTR_TYPE(SPEC_OCLS(etype));
11324
11325       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11326
11327       if (SPEC_OCLS(etype)->codesp ) {
11328         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11329         //p_type = CPOINTER ;   
11330       } else
11331       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11332         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11333         /*p_type = FPOINTER ;*/ 
11334       } else
11335       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11336         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11337         /* p_type = PPOINTER; */
11338       } else
11339       if (SPEC_OCLS(etype) == idata ) {
11340         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11341         /* p_type = IPOINTER; */
11342       } else {
11343         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11344         /* p_type = POINTER ; */
11345       }
11346     }
11347
11348     /* now that we have the pointer type we assign
11349     the pointer values */
11350     switch (p_type) {
11351       case POINTER:     
11352       case FPOINTER:
11353       case IPOINTER:
11354         genNearPointerGet (left,result,ic);
11355         break;
11356
11357       case PPOINTER:
11358         genPagedPointerGet(left,result,ic);
11359         break;
11360
11361 #if 0
11362       /* PICs do not support FAR pointers... */
11363       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11364       case FPOINTER:
11365         genFarPointerGet (left,result,ic);
11366         break;
11367 #endif
11368
11369       case CPOINTER:
11370         genConstPointerGet (left,result,ic);
11371         //pic16_emitcodePointerGet (left,result,ic);
11372         break;
11373
11374       case GPOINTER:
11375 #if 0
11376       if (IS_PTR_CONST(type))
11377         genConstPointerGet (left,result,ic);
11378       else
11379 #endif
11380         genGenPointerGet (left,result,ic);
11381       break;
11382
11383     default:
11384       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11385               "genPointerGet: illegal pointer type");
11386     
11387     }
11388 }
11389
11390 /*-----------------------------------------------------------------*/
11391 /* genPackBits - generates code for packed bit storage             */
11392 /*-----------------------------------------------------------------*/
11393 static void genPackBits (sym_link    *etype , operand *result,
11394                          operand *right ,
11395                          char *rname, int p_type)
11396 {
11397   int shCnt = 0 ;
11398   int offset = 0  ;
11399   int rLen = 0 ;
11400   int blen, bstr ;   
11401   int shifted_and_masked = 0;
11402   unsigned long lit = (unsigned long)-1;
11403   sym_link *retype;
11404
11405   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11406   blen = SPEC_BLEN(etype);
11407   bstr = SPEC_BSTR(etype);
11408
11409   retype = getSpec(operandType(right));
11410
11411   if(AOP_TYPE(right) == AOP_LIT) {
11412     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11413     
11414     if((blen == 1) && (bstr < 8)) {
11415       /* it is a single bit, so use the appropriate bit instructions */
11416
11417       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11418
11419       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11420         /* workaround to reduce the extra lfsr instruction */
11421         if(lit) {
11422           pic16_emitpcode(POC_BSF,
11423               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11424         } else {
11425           pic16_emitpcode(POC_BCF,
11426               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11427         }
11428       } else {
11429         if (PIC_IS_DATA_PTR(operandType(result))) {
11430           pic16_loadFSR0(result, 0);
11431           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11432               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11433         } else {
11434           /* get old value */
11435           pic16_derefPtr (result, p_type, 0, NULL);
11436           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11437               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11438           /* write back new value */
11439           pic16_derefPtr (result, p_type, 1, NULL);
11440         }
11441       }
11442
11443       return;
11444     }
11445     /* IORLW below is more efficient */
11446     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11447     lit = (lit & ((1UL << blen) - 1)) << bstr;
11448     shifted_and_masked = 1;
11449     offset++;
11450   } else
11451     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11452         && IS_BITFIELD(retype) 
11453         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11454         && (blen == 1)) {
11455       int rblen, rbstr;
11456
11457       rblen = SPEC_BLEN( retype );
11458       rbstr = SPEC_BSTR( retype );
11459
11460       if(IS_BITFIELD(etype)) {
11461         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11462         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11463       } else {
11464         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11465       }
11466
11467       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11468
11469       if(IS_BITFIELD(etype)) {
11470         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11471       } else {
11472         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11473       }
11474
11475       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11476
11477       return;
11478     } else {
11479       /* move right to W */
11480       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11481     }
11482
11483   /* if the bit length is less than or   */
11484   /* it exactly fits a byte then         */
11485   if((shCnt=SPEC_BSTR(etype))
11486       || SPEC_BLEN(etype) <= 8 )  {
11487     int fsr0_setup = 0;
11488
11489     if (blen != 8 || bstr != 0) {
11490       // we need to combine the value with the old value
11491       if(!shifted_and_masked)
11492       {
11493         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11494
11495         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11496             SPEC_BSTR(etype), SPEC_BLEN(etype));
11497
11498         /* shift left acc, do NOT mask the result again */
11499         AccLsh(shCnt, 0);
11500
11501         /* using PRODH as a temporary register here */
11502         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11503       }
11504
11505       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11506         || IS_DIRECT(result)) {
11507         /* access symbol directly */
11508         pic16_mov2w (AOP(result), 0);
11509       } else {
11510         /* get old value */
11511         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11512       }
11513 #if 1
11514       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11515             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11516                             (unsigned char)(0xff >> (8-bstr))) ));
11517       if (!shifted_and_masked) {
11518         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11519       } else {
11520         /* We have the shifted and masked (literal) right value in `lit' */
11521         if (lit != 0)
11522           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11523       }
11524     } // if (blen != 8 || bstr != 0)
11525
11526     /* write new value back */
11527     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11528         || IS_DIRECT(result)) {
11529       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11530     } else {
11531       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11532     }
11533 #endif
11534
11535     return;
11536   }
11537
11538
11539 #if 0
11540   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11541   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11542   exit(-1);
11543 #endif
11544
11545
11546   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11547   rLen = SPEC_BLEN(etype)-8;
11548
11549   /* now generate for lengths greater than one byte */
11550   while (1) {
11551     rLen -= 8 ;
11552     if (rLen <= 0 ) {
11553       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11554       break ;
11555     }
11556
11557     switch (p_type) {
11558       case POINTER:
11559         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11560         break;
11561
11562         /*
11563            case FPOINTER:
11564            MOVA(l);
11565            pic16_emitcode("movx","@dptr,a");
11566            break;
11567
11568            case GPOINTER:
11569            MOVA(l);
11570            DEBUGpic16_emitcode(";lcall","__gptrput");
11571            break;  
11572          */
11573       default:
11574         assert(0);
11575     }   
11576
11577
11578     pic16_mov2w(AOP(right), offset++);
11579   }
11580
11581   /* last last was not complete */
11582   if (rLen)   {
11583     /* save the byte & read byte */
11584     switch (p_type) {
11585       case POINTER:
11586         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11587         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11588         break;
11589
11590         /*
11591            case FPOINTER:
11592            pic16_emitcode ("mov","b,a");
11593            pic16_emitcode("movx","a,@dptr");
11594            break;
11595
11596            case GPOINTER:
11597            pic16_emitcode ("push","b");
11598            pic16_emitcode ("push","acc");
11599            pic16_emitcode ("lcall","__gptrget");
11600            pic16_emitcode ("pop","b");
11601            break;
11602          */
11603       default:
11604         assert(0);
11605     }
11606     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11607     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11608     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11609     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11610     //        pic16_emitcode ("orl","a,b");
11611   }
11612
11613   //    if (p_type == GPOINTER)
11614   //        pic16_emitcode("pop","b");
11615
11616   switch (p_type) {
11617
11618     case POINTER:
11619       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11620       //        pic16_emitcode("mov","@%s,a",rname);
11621       break;
11622       /*
11623          case FPOINTER:
11624          pic16_emitcode("movx","@dptr,a");
11625          break;
11626
11627          case GPOINTER:
11628          DEBUGpic16_emitcode(";lcall","__gptrput");
11629          break;                 
11630        */
11631     default:
11632       assert(0);
11633   }
11634
11635   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11636 }
11637
11638 /*-----------------------------------------------------------------*/
11639 /* genDataPointerSet - remat pointer to data space                 */
11640 /*-----------------------------------------------------------------*/
11641 static void genDataPointerSet(operand *right,
11642                               operand *result,
11643                               iCode *ic)
11644 {
11645   int size, offset = 0, resoffset=0 ;
11646
11647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11648     pic16_aopOp(right,ic,FALSE);
11649
11650     size = AOP_SIZE(right);
11651
11652 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11653
11654 #if 0
11655     if ( AOP_TYPE(result) == AOP_PCODE) {
11656       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11657               AOP(result)->aopu.pcop->name,
11658                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11659               PCOR(AOP(result)->aopu.pcop)->instance:
11660               PCOI(AOP(result)->aopu.pcop)->offset);
11661     }
11662 #endif
11663
11664     if(AOP(result)->aopu.pcop->type == PO_DIR)
11665       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11666
11667     while (size--) {
11668       if (AOP_TYPE(right) == AOP_LIT) {
11669         unsigned int lit;
11670
11671           if(!IS_FLOAT(operandType( right )))
11672             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11673           else {
11674             union {
11675               unsigned long lit_int;
11676               float lit_float;
11677             } info;
11678         
11679               /* take care if literal is a float */
11680               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11681               lit = info.lit_int;
11682           }
11683                     lit = lit >> (8*offset);
11684                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11685                 } else {
11686                   pic16_mov2w(AOP(right), offset);
11687                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11688                 }
11689                 offset++;
11690                 resoffset++;
11691         }
11692
11693     pic16_freeAsmop(right,NULL,ic,TRUE);
11694 }
11695
11696
11697
11698 /*-----------------------------------------------------------------*/
11699 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11700 /*-----------------------------------------------------------------*/
11701 static void genNearPointerSet (operand *right,
11702                                operand *result, 
11703                                iCode *ic)
11704 {
11705   asmop *aop = NULL;
11706   sym_link *retype;
11707   sym_link *ptype = operandType(result);
11708   sym_link *resetype;
11709     
11710     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11711     retype= getSpec(operandType(right));
11712     resetype = getSpec(operandType(result));
11713   
11714     pic16_aopOp(result,ic,FALSE);
11715     
11716     /* if the result is rematerializable &
11717      * in data space & not a bit variable */
11718         
11719     /* and result is not a bit variable */
11720     if (AOP_TYPE(result) == AOP_PCODE
11721 //      && AOP_TYPE(result) == AOP_IMMD
11722       && DCL_TYPE(ptype) == POINTER
11723       && !IS_BITFIELD(retype)
11724       && !IS_BITFIELD(resetype)) {
11725
11726         genDataPointerSet (right,result,ic);
11727         pic16_freeAsmop(result,NULL,ic,TRUE);
11728       return;
11729     }
11730
11731     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11732     pic16_aopOp(right,ic,FALSE);
11733     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11734
11735     /* if bitfield then unpack the bits */
11736     if (IS_BITFIELD(resetype)) {
11737       genPackBits (resetype, result, right, NULL, POINTER);
11738     } else {
11739       /* we have can just get the values */
11740       int size = AOP_SIZE(right);
11741       int offset = 0 ;    
11742
11743         pic16_loadFSR0(result, 0);
11744             
11745         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11746         while (size--) {
11747           if (AOP_TYPE(right) == AOP_LIT) {
11748             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11749             if (size) {
11750               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11751             } else {
11752               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11753             }
11754           } else { // no literal
11755             if(size) {
11756               pic16_emitpcode(POC_MOVFF,
11757                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11758                   pic16_popCopyReg(&pic16_pc_postinc0)));
11759             } else {
11760               pic16_emitpcode(POC_MOVFF,
11761                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11762                   pic16_popCopyReg(&pic16_pc_indf0)));
11763             }
11764           }
11765           
11766           offset++;
11767         }
11768     }
11769
11770     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11771     /* now some housekeeping stuff */
11772     if (aop) {
11773       /* we had to allocate for this iCode */
11774       pic16_freeAsmop(NULL,aop,ic,TRUE);
11775     } else { 
11776       /* we did not allocate which means left
11777        * already in a pointer register, then
11778        * if size > 0 && this could be used again
11779        * we have to point it back to where it 
11780        * belongs */
11781       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11782       if (AOP_SIZE(right) > 1
11783         && !OP_SYMBOL(result)->remat
11784         && ( OP_SYMBOL(result)->liveTo > ic->seq
11785         || ic->depth )) {
11786
11787           int size = AOP_SIZE(right) - 1;
11788
11789             while (size--)
11790               pic16_emitcode("decf","fsr0,f");
11791               //pic16_emitcode("dec","%s",rname);
11792       }
11793     }
11794
11795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11796     /* done */
11797 //release:
11798     pic16_freeAsmop(right,NULL,ic,TRUE);
11799     pic16_freeAsmop(result,NULL,ic,TRUE);
11800 }
11801
11802 /*-----------------------------------------------------------------*/
11803 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11804 /*-----------------------------------------------------------------*/
11805 static void genPagedPointerSet (operand *right,
11806                                operand *result, 
11807                                iCode *ic)
11808 {
11809     asmop *aop = NULL;
11810     regs *preg = NULL ;
11811     char *rname , *l;
11812     sym_link *retype;
11813        
11814     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11815
11816     retype= getSpec(operandType(right));
11817     
11818     pic16_aopOp(result,ic,FALSE);
11819     
11820     /* if the value is already in a pointer register
11821        then don't need anything more */
11822     if (!AOP_INPREG(AOP(result))) {
11823         /* otherwise get a free pointer register */
11824         aop = newAsmop(0);
11825         preg = getFreePtr(ic,&aop,FALSE);
11826         pic16_emitcode("mov","%s,%s",
11827                 preg->name,
11828                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11829         rname = preg->name ;
11830     } else
11831         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11832     
11833     pic16_freeAsmop(result,NULL,ic,TRUE);
11834     pic16_aopOp (right,ic,FALSE);
11835
11836     /* if bitfield then unpack the bits */
11837     if (IS_BITFIELD(retype)) 
11838         genPackBits (retype,result,right,rname,PPOINTER);
11839     else {
11840         /* we have can just get the values */
11841         int size = AOP_SIZE(right);
11842         int offset = 0 ;        
11843         
11844         while (size--) {
11845             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11846             
11847             MOVA(l);
11848             pic16_emitcode("movx","@%s,a",rname);
11849
11850             if (size)
11851                 pic16_emitcode("inc","%s",rname);
11852
11853             offset++;
11854         }
11855     }
11856     
11857     /* now some housekeeping stuff */
11858     if (aop) {
11859         /* we had to allocate for this iCode */
11860         pic16_freeAsmop(NULL,aop,ic,TRUE);
11861     } else { 
11862         /* we did not allocate which means left
11863            already in a pointer register, then
11864            if size > 0 && this could be used again
11865            we have to point it back to where it 
11866            belongs */
11867         if (AOP_SIZE(right) > 1 &&
11868             !OP_SYMBOL(result)->remat &&
11869             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11870               ic->depth )) {
11871             int size = AOP_SIZE(right) - 1;
11872             while (size--)
11873                 pic16_emitcode("dec","%s",rname);
11874         }
11875     }
11876
11877     /* done */
11878     pic16_freeAsmop(right,NULL,ic,TRUE);
11879     
11880         
11881 }
11882
11883 #if 0
11884 /* This code is not adjusted to PIC16 and fails utterly...
11885  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11886
11887 /*-----------------------------------------------------------------*/
11888 /* genFarPointerSet - set value from far space                     */
11889 /*-----------------------------------------------------------------*/
11890 static void genFarPointerSet (operand *right,
11891                               operand *result, iCode *ic)
11892 {
11893     int size, offset ;
11894     sym_link *retype = getSpec(operandType(right));
11895
11896     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11897     pic16_aopOp(result,ic,FALSE);
11898
11899     /* if the operand is already in dptr 
11900     then we do nothing else we move the value to dptr */
11901     if (AOP_TYPE(result) != AOP_STR) {
11902         /* if this is remateriazable */
11903         if (AOP_TYPE(result) == AOP_IMMD)
11904             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11905         else { /* we need to get it byte by byte */
11906             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11907             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11908             if (options.model == MODEL_FLAT24)
11909             {
11910                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11911             }
11912         }
11913     }
11914     /* so dptr know contains the address */
11915     pic16_freeAsmop(result,NULL,ic,TRUE);
11916     pic16_aopOp(right,ic,FALSE);
11917
11918     /* if bit then unpack */
11919     if (IS_BITFIELD(retype)) 
11920         genPackBits(retype,result,right,"dptr",FPOINTER);
11921     else {
11922         size = AOP_SIZE(right);
11923         offset = 0 ;
11924
11925         while (size--) {
11926             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11927             MOVA(l);
11928             pic16_emitcode("movx","@dptr,a");
11929             if (size)
11930                 pic16_emitcode("inc","dptr");
11931         }
11932     }
11933
11934     pic16_freeAsmop(right,NULL,ic,TRUE);
11935 }
11936 #endif
11937
11938 /*-----------------------------------------------------------------*/
11939 /* genGenPointerSet - set value from generic pointer space         */
11940 /*-----------------------------------------------------------------*/
11941 #if 0
11942 static void genGenPointerSet (operand *right,
11943                               operand *result, iCode *ic)
11944 {
11945         int i, size, offset, lit;
11946         sym_link *retype = getSpec(operandType(right));
11947
11948         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11949
11950         pic16_aopOp(result,ic,FALSE);
11951         pic16_aopOp(right,ic,FALSE);
11952         size = AOP_SIZE(right);
11953         offset = 0;
11954
11955         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11956
11957         /* if the operand is already in dptr 
11958                 then we do nothing else we move the value to dptr */
11959         if (AOP_TYPE(result) != AOP_STR) {
11960                 /* if this is remateriazable */
11961                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11962                 // WARNING: anythig until "else" is untested!
11963                 if (AOP_TYPE(result) == AOP_IMMD) {
11964                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11965                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11966                         // load FSR0 from immediate
11967                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11968                         offset = 0;
11969                         while(size--) {
11970                                 if(size) {
11971                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11972                                 } else {
11973                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11974                                 }
11975                                 offset++;
11976                         }
11977                         goto release;
11978                 }
11979                 else { /* we need to get it byte by byte */
11980                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11981                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11982
11983                         // set up FSR0 with address of result
11984                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11985                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11986
11987                         /* hack hack! see if this the FSR. If so don't load W */
11988                         if(AOP_TYPE(right) != AOP_ACC) {
11989
11990                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11991
11992                                 if(AOP_TYPE(right) == AOP_LIT)
11993                                 {
11994                                         // copy literal
11995                                         // note: pic16_popGet handles sign extension
11996                                         for(i=0;i<size;i++) {
11997                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11998                                                 if(i < size-1)
11999                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12000                                                 else
12001                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12002                                         }
12003                                 } else {
12004                                         // copy regs
12005
12006                                         for(i=0;i<size;i++) {
12007                                                 if(i < size-1)
12008                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12009                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12010                                                 else
12011                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12012                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12013                                         }
12014                                 }
12015                                 goto release;
12016                         } 
12017                         // right = ACC
12018                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12019                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12020                         goto release;
12021         } // if (AOP_TYPE(result) != AOP_IMMD)
12022
12023         } // if (AOP_TYPE(result) != AOP_STR)
12024         /* so dptr know contains the address */
12025
12026
12027         /* if bit then unpack */
12028         if (IS_BITFIELD(retype)) 
12029                 genPackBits(retype,result,right,"dptr",GPOINTER);
12030         else {
12031                 size = AOP_SIZE(right);
12032                 offset = 0 ;
12033
12034                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12035
12036                 // set up FSR0 with address of result
12037                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12038                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12039         
12040                 while (size--) {
12041                         if (AOP_TYPE(right) == AOP_LIT) {
12042                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12043                                 if (size) {
12044                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12045                                 } else {
12046                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12047                                 }
12048                         } else { // no literal
12049                                 if(size) {
12050                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12051                                 } else {
12052                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12053                                 }
12054                         }
12055                         offset++;
12056                 }
12057         }
12058
12059         release:
12060         pic16_freeAsmop(right,NULL,ic,TRUE);
12061         pic16_freeAsmop(result,NULL,ic,TRUE);
12062 }
12063 #endif
12064
12065 static void genGenPointerSet (operand *right,
12066                               operand *result, iCode *ic)
12067 {
12068   int size;
12069   sym_link *retype = getSpec(operandType(result));
12070
12071     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12072
12073     pic16_aopOp(result,ic,FALSE);
12074     pic16_aopOp(right,ic,FALSE);
12075     size = AOP_SIZE(right);
12076
12077     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12078
12079
12080     /* if bit then unpack */
12081     if (IS_BITFIELD(retype)) {
12082 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12083       genPackBits(retype,result,right,"dptr",GPOINTER);
12084       goto release;
12085     }
12086
12087     size = AOP_SIZE(right);
12088
12089     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12090
12091
12092     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12093
12094     /* value of right+0 is placed on stack, which will be retrieved
12095      * by the support function thus restoring the stack. The important
12096      * thing is that there is no need to manually restore stack pointer
12097      * here */
12098     pushaop(AOP(right), 0);
12099 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12100     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12101     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12102     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12103     
12104     /* load address to write to in WREG:FSR0H:FSR0L */
12105     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12106                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12107     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12108                                 pic16_popCopyReg(&pic16_pc_prodl)));
12109     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12110     
12111     pic16_callGenericPointerRW(1, size);
12112
12113 release:
12114     pic16_freeAsmop(right,NULL,ic,TRUE);
12115     pic16_freeAsmop(result,NULL,ic,TRUE);
12116 }
12117
12118 /*-----------------------------------------------------------------*/
12119 /* genPointerSet - stores the value into a pointer location        */
12120 /*-----------------------------------------------------------------*/
12121 static void genPointerSet (iCode *ic)
12122 {    
12123   operand *right, *result ;
12124   sym_link *type, *etype;
12125   int p_type;
12126
12127     FENTRY;
12128
12129     right = IC_RIGHT(ic);
12130     result = IC_RESULT(ic) ;
12131
12132     /* depending on the type of pointer we need to
12133     move it to the correct pointer register */
12134     type = operandType(result);
12135     etype = getSpec(type);
12136     
12137     /* if left is of type of pointer then it is simple */
12138     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12139         p_type = DCL_TYPE(type);
12140     }
12141     else {
12142         /* we have to go by the storage class */
12143         p_type = PTR_TYPE(SPEC_OCLS(etype));
12144
12145 /*      if (SPEC_OCLS(etype)->codesp ) { */
12146 /*          p_type = CPOINTER ;  */
12147 /*      } */
12148 /*      else */
12149 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12150 /*              p_type = FPOINTER ; */
12151 /*          else */
12152 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12153 /*                  p_type = PPOINTER ; */
12154 /*              else */
12155 /*                  if (SPEC_OCLS(etype) == idata ) */
12156 /*                      p_type = IPOINTER ; */
12157 /*                  else */
12158 /*                      p_type = POINTER ; */
12159     }
12160
12161     /* now that we have the pointer type we assign
12162     the pointer values */
12163     switch (p_type) {
12164       case POINTER:
12165       case FPOINTER:
12166       case IPOINTER:
12167         genNearPointerSet (right,result,ic);
12168         break;
12169
12170       case PPOINTER:
12171         genPagedPointerSet (right,result,ic);
12172         break;
12173
12174 #if 0
12175       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12176       case FPOINTER:
12177         genFarPointerSet (right,result,ic);
12178         break;
12179 #endif
12180         
12181       case GPOINTER:
12182         genGenPointerSet (right,result,ic);
12183         break;
12184
12185       default:
12186         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12187           "genPointerSet: illegal pointer type");
12188     }
12189 }
12190
12191 /*-----------------------------------------------------------------*/
12192 /* genIfx - generate code for Ifx statement                        */
12193 /*-----------------------------------------------------------------*/
12194 static void genIfx (iCode *ic, iCode *popIc)
12195 {
12196   operand *cond = IC_COND(ic);
12197   int isbit =0;
12198
12199     FENTRY;
12200
12201     pic16_aopOp(cond,ic,FALSE);
12202
12203     /* get the value into acc */
12204     if (AOP_TYPE(cond) != AOP_CRY)
12205       pic16_toBoolean(cond);
12206     else
12207       isbit = 1;
12208     /* the result is now in the accumulator */
12209     pic16_freeAsmop(cond,NULL,ic,TRUE);
12210
12211     /* if there was something to be popped then do it */
12212     if (popIc)
12213       genIpop(popIc);
12214
12215     /* if the condition is  a bit variable */
12216     if (isbit && IS_ITEMP(cond) && 
12217         SPIL_LOC(cond)) {
12218       genIfxJump(ic,"c");
12219       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12220     } else {
12221       if (isbit && !IS_ITEMP(cond))
12222         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12223         else
12224         genIfxJump(ic,"a");
12225     }
12226     ic->generated = 1;
12227 }
12228
12229 /*-----------------------------------------------------------------*/
12230 /* genAddrOf - generates code for address of                       */
12231 /*-----------------------------------------------------------------*/
12232 static void genAddrOf (iCode *ic)
12233 {
12234   operand *result, *left;
12235   int size;
12236   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12237   pCodeOp *pcop0, *pcop1, *pcop2;
12238
12239     FENTRY;
12240
12241     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12242
12243     sym = OP_SYMBOL( IC_LEFT(ic) );
12244     
12245     if(sym->onStack) {
12246       /* get address of symbol on stack */
12247       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12248 #if 0
12249       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12250                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12251 #endif
12252
12253       // operands on stack are accessible via "FSR2 + index" with index
12254       // starting at 2 for arguments and growing from 0 downwards for
12255       // local variables (index == 0 is not assigned so we add one here)
12256       {
12257         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12258
12259           if (soffs <= 0) {
12260             assert (soffs < 0);
12261             soffs++;
12262           } // if
12263
12264           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12265           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12266           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12267           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12268           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12269           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12270           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12271       }
12272
12273       goto release;
12274     }
12275         
12276 //      if(pic16_debug_verbose) {
12277 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12278 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12279 //      }
12280         
12281     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12282     size = AOP_SIZE(IC_RESULT(ic));
12283
12284     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12285     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12286     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12287         
12288     if (size == 3) {
12289       pic16_emitpcode(POC_MOVLW, pcop0);
12290       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12291       pic16_emitpcode(POC_MOVLW, pcop1);
12292       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12293       pic16_emitpcode(POC_MOVLW, pcop2);
12294       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12295     } else
12296     if (size == 2) {
12297       pic16_emitpcode(POC_MOVLW, pcop0);
12298       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12299       pic16_emitpcode(POC_MOVLW, pcop1);
12300     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12301     } else {
12302       pic16_emitpcode(POC_MOVLW, pcop0);
12303       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12304     }
12305
12306     pic16_freeAsmop(left, NULL, ic, FALSE);
12307 release:
12308     pic16_freeAsmop(result,NULL,ic,TRUE);
12309 }
12310
12311
12312 #if 0
12313 /*-----------------------------------------------------------------*/
12314 /* genFarFarAssign - assignment when both are in far space         */
12315 /*-----------------------------------------------------------------*/
12316 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12317 {
12318     int size = AOP_SIZE(right);
12319     int offset = 0;
12320     char *l ;
12321     /* first push the right side on to the stack */
12322     while (size--) {
12323         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12324         MOVA(l);
12325         pic16_emitcode ("push","acc");
12326     }
12327     
12328     pic16_freeAsmop(right,NULL,ic,FALSE);
12329     /* now assign DPTR to result */
12330     pic16_aopOp(result,ic,FALSE);
12331     size = AOP_SIZE(result);
12332     while (size--) {
12333         pic16_emitcode ("pop","acc");
12334         pic16_aopPut(AOP(result),"a",--offset);
12335     }
12336     pic16_freeAsmop(result,NULL,ic,FALSE);
12337         
12338 }
12339 #endif
12340
12341 /*-----------------------------------------------------------------*/
12342 /* genAssign - generate code for assignment                        */
12343 /*-----------------------------------------------------------------*/
12344 static void genAssign (iCode *ic)
12345 {
12346   operand *result, *right;
12347   sym_link *restype, *rtype;
12348   int size, offset,know_W;
12349   unsigned long lit = 0L;
12350
12351     result = IC_RESULT(ic);
12352     right  = IC_RIGHT(ic) ;
12353
12354     FENTRY;
12355   
12356     /* if they are the same */
12357     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12358       return ;
12359
12360     /* reversed order operands are aopOp'ed so that result operand
12361      * is effective in case right is a stack symbol. This maneauver
12362      * allows to use the _G.resDirect flag later */
12363      pic16_aopOp(result,ic,TRUE);
12364     pic16_aopOp(right,ic,FALSE);
12365
12366     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12367
12368     /* if they are the same registers */
12369     if (pic16_sameRegs(AOP(right),AOP(result)))
12370       goto release;
12371
12372     /* if the result is a bit */
12373     if (AOP_TYPE(result) == AOP_CRY) {
12374       /* if the right size is a literal then
12375          we know what the value is */
12376       if (AOP_TYPE(right) == AOP_LIT) {
12377           
12378         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12379             pic16_popGet(AOP(result),0));
12380
12381         if (((int) operandLitValue(right))) 
12382           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12383               AOP(result)->aopu.aop_dir,
12384               AOP(result)->aopu.aop_dir);
12385         else
12386           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12387               AOP(result)->aopu.aop_dir,
12388               AOP(result)->aopu.aop_dir);
12389         
12390         goto release;
12391       }
12392
12393       /* the right is also a bit variable */
12394       if (AOP_TYPE(right) == AOP_CRY) {
12395         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12396         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12397         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12398
12399         goto release ;
12400       }
12401
12402       /* we need to or */
12403       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12404       pic16_toBoolean(right);
12405       emitSKPZ;
12406       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12407       //pic16_aopPut(AOP(result),"a",0);
12408       goto release ;
12409     }
12410
12411     /* bit variables done */
12412     /* general case */
12413     size = AOP_SIZE(result);
12414     offset = 0 ;
12415
12416   /* bit variables done */
12417   /* general case */
12418   size = AOP_SIZE(result);
12419   restype = operandType(result);
12420   rtype = operandType(right);
12421   offset = 0 ;
12422
12423   if(AOP_TYPE(right) == AOP_LIT) {
12424     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12425     {
12426       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12427
12428       /* patch tag for literals that are cast to pointers */
12429       if (IS_CODEPTR(restype)) {
12430         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12431         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12432       } else {
12433         if (IS_GENPTR(restype))
12434         {
12435           if (IS_CODEPTR(rtype)) {
12436             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12437             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12438           } else if (PIC_IS_DATA_PTR(rtype)) {
12439             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12440             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12441           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12442             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12443           } else if (IS_PTR(rtype)) {
12444             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12445             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12446           }
12447         }
12448       }
12449     } else {
12450       union {
12451         unsigned long lit_int;
12452         float lit_float;
12453       } info;
12454
12455
12456       if(IS_FIXED16X16(operandType(right))) {
12457         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12458       } else {
12459         /* take care if literal is a float */
12460         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12461         lit = info.lit_int;
12462       }
12463     }
12464   }
12465
12466 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12467 //                      sizeof(unsigned long int), sizeof(float));
12468
12469
12470     if (AOP_TYPE(right) == AOP_REG) {
12471       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12472       while (size--) {
12473         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12474       } // while
12475       goto release;
12476     }
12477
12478     /* when do we have to read the program memory?
12479      * - if right itself is a symbol in code space
12480      *   (we don't care what it points to if it's a pointer)
12481      * - AND right is not a function (we would want its address)
12482      */
12483     if(AOP_TYPE(right) != AOP_LIT
12484       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12485       && !IS_FUNC(OP_SYM_TYPE(right))
12486       && !IS_ITEMP(right)) {
12487
12488       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12489       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12490       
12491       // set up table pointer
12492       if(is_LitOp(right)) {
12493 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12494         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12495         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12496         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12497         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12498         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12499         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12500       } else {
12501 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12502         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12503             pic16_popCopyReg(&pic16_pc_tblptrl)));
12504         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12505             pic16_popCopyReg(&pic16_pc_tblptrh)));
12506         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12507             pic16_popCopyReg(&pic16_pc_tblptru)));
12508       }
12509
12510       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12511       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12512       while(size--) {
12513         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12514         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12515             pic16_popGet(AOP(result),offset)));
12516         offset++;
12517       }
12518
12519       /* FIXME: for pointers we need to extend differently (according
12520        * to pointer type DATA/CODE/EEPROM/... :*/
12521       size = getSize(OP_SYM_TYPE(right));
12522       if(AOP_SIZE(result) > size) {
12523         size = AOP_SIZE(result) - size;
12524         while(size--) {
12525           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12526           offset++;
12527         }
12528       }
12529       goto release;
12530     }
12531
12532 #if 0
12533     /* VR - What is this?! */
12534     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12535       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12536       
12537       if(aopIdx(AOP(result),0) == 4) {
12538         /* this is a workaround to save value of right into wreg too,
12539          * value of wreg is going to be used later */
12540         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12541         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12542         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12543         goto release;
12544       } else
12545 //      assert(0);
12546       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12547     }
12548 #endif
12549
12550   know_W=-1;
12551   while (size--) {
12552     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12553     if(AOP_TYPE(right) == AOP_LIT) {
12554       if(lit&0xff) {
12555         if(know_W != (lit&0xff))
12556           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12557         know_W = lit&0xff;
12558         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12559       } else
12560         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12561
12562       lit >>= 8;
12563
12564     } else if (AOP_TYPE(right) == AOP_CRY) {
12565       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12566       if(offset == 0) {
12567         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12568         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12569         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12570       }
12571     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12572         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12573         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12574     } else {
12575       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12576
12577       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12578           if(AOP_TYPE(result) == AOP_ACC) {
12579             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12580           } else
12581           if(AOP_TYPE(right) == AOP_ACC) {
12582             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12583           } else {
12584             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12585           }
12586       }
12587     }
12588       
12589       offset++;
12590     }
12591   
12592 release:
12593   pic16_freeAsmop (right,NULL,ic,FALSE);
12594   pic16_freeAsmop (result,NULL,ic,TRUE);
12595
12596
12597 /*-----------------------------------------------------------------*/
12598 /* genJumpTab - generates code for jump table                       */
12599 /*-----------------------------------------------------------------*/
12600 static void genJumpTab (iCode *ic)
12601 {
12602   symbol *jtab;
12603   char *l;
12604   pCodeOp *jt_offs;
12605   pCodeOp *jt_offs_hi;
12606   pCodeOp *jt_label;
12607
12608     FENTRY;
12609
12610     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12611     /* get the condition into accumulator */
12612     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12613     MOVA(l);
12614     /* multiply by three */
12615     pic16_emitcode("add","a,acc");
12616     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12617
12618     jtab = newiTempLabel(NULL);
12619     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12620     pic16_emitcode("jmp","@a+dptr");
12621     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12622
12623 #if 0
12624     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12625     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12626     emitSKPNC;
12627     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12628     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12629     pic16_emitpLabel(jtab->key);
12630
12631 #else
12632
12633     jt_offs = pic16_popGetTempReg(0);
12634     jt_offs_hi = pic16_popGetTempReg(1);
12635     jt_label = pic16_popGetLabel (jtab->key);
12636     //fprintf (stderr, "Creating jump table...\n");
12637
12638     // calculate offset into jump table (idx * sizeof (GOTO))
12639     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12640     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12641     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12642     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12643     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12644     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12645     pic16_emitpcode(POC_MOVWF , jt_offs);
12646
12647     // prepare PCLATx (set to first entry in jump table)
12648     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12649     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12650     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12651     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12652     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12653
12654     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12655     pic16_emitpcode(POC_ADDWF , jt_offs);
12656     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12657     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12658     emitSKPNC;
12659     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12660
12661     // release temporaries and prepare jump into table (new PCL --> WREG)
12662     pic16_emitpcode(POC_MOVFW , jt_offs);
12663     pic16_popReleaseTempReg (jt_offs_hi, 1);
12664     pic16_popReleaseTempReg (jt_offs, 0);
12665
12666     // jump into the table
12667     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12668
12669     pic16_emitpLabelFORCE(jtab->key);
12670 #endif
12671
12672     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12673 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12674
12675     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12676     /* now generate the jump labels */
12677     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12678          jtab = setNextItem(IC_JTLABELS(ic))) {
12679 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12680         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12681         
12682     }
12683     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12684
12685 }
12686
12687 /*-----------------------------------------------------------------*/
12688 /* genMixedOperation - gen code for operators between mixed types  */
12689 /*-----------------------------------------------------------------*/
12690 /*
12691   TSD - Written for the PIC port - but this unfortunately is buggy.
12692   This routine is good in that it is able to efficiently promote 
12693   types to different (larger) sizes. Unfortunately, the temporary
12694   variables that are optimized out by this routine are sometimes
12695   used in other places. So until I know how to really parse the 
12696   iCode tree, I'm going to not be using this routine :(.
12697 */
12698 static int genMixedOperation (iCode *ic)
12699 {
12700 #if 0
12701   operand *result = IC_RESULT(ic);
12702   sym_link *ctype = operandType(IC_LEFT(ic));
12703   operand *right = IC_RIGHT(ic);
12704   int ret = 0;
12705   int big,small;
12706   int offset;
12707
12708   iCode *nextic;
12709   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12710
12711   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12712
12713   nextic = ic->next;
12714   if(!nextic)
12715     return 0;
12716
12717   nextright = IC_RIGHT(nextic);
12718   nextleft  = IC_LEFT(nextic);
12719   nextresult = IC_RESULT(nextic);
12720
12721   pic16_aopOp(right,ic,FALSE);
12722   pic16_aopOp(result,ic,FALSE);
12723   pic16_aopOp(nextright,  nextic, FALSE);
12724   pic16_aopOp(nextleft,   nextic, FALSE);
12725   pic16_aopOp(nextresult, nextic, FALSE);
12726
12727   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12728
12729     operand *t = right;
12730     right = nextright;
12731     nextright = t; 
12732
12733     pic16_emitcode(";remove right +","");
12734
12735   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12736 /*
12737     operand *t = right;
12738     right = nextleft;
12739     nextleft = t; 
12740 */
12741     pic16_emitcode(";remove left +","");
12742   } else
12743     return 0;
12744
12745   big = AOP_SIZE(nextleft);
12746   small = AOP_SIZE(nextright);
12747
12748   switch(nextic->op) {
12749
12750   case '+':
12751     pic16_emitcode(";optimize a +","");
12752     /* if unsigned or not an integral type */
12753     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12754       pic16_emitcode(";add a bit to something","");
12755     } else {
12756
12757       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12758
12759       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12760         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12761         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12762       } else
12763         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12764
12765       offset = 0;
12766       while(--big) {
12767
12768         offset++;
12769
12770         if(--small) {
12771           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12772             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12773             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12774           }
12775
12776           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12777           emitSKPNC;
12778           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12779                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12780                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12781           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12782           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12783
12784         } else {
12785           pic16_emitcode("rlf","known_zero,w");
12786
12787           /*
12788             if right is signed
12789               btfsc  right,7
12790                addlw ff
12791           */
12792           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12793             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12794             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12795           } else {
12796             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12797           }
12798         }
12799       }
12800       ret = 1;
12801     }
12802   }
12803   ret = 1;
12804
12805 release:
12806   pic16_freeAsmop(right,NULL,ic,TRUE);
12807   pic16_freeAsmop(result,NULL,ic,TRUE);
12808   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12809   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12810   if(ret)
12811     nextic->generated = 1;
12812
12813   return ret;
12814 #else
12815   return 0;
12816 #endif
12817 }
12818 /*-----------------------------------------------------------------*/
12819 /* genCast - gen code for casting                                  */
12820 /*-----------------------------------------------------------------*/
12821 static void genCast (iCode *ic)
12822 {
12823   operand *result = IC_RESULT(ic);
12824   sym_link *ctype = operandType(IC_LEFT(ic));
12825   sym_link *rtype = operandType(IC_RIGHT(ic));
12826   sym_link *restype = operandType(IC_RESULT(ic));
12827   operand *right = IC_RIGHT(ic);
12828   int size, offset ;
12829
12830
12831     FENTRY;
12832
12833         /* if they are equivalent then do nothing */
12834 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12835 //              return ;
12836
12837         pic16_aopOp(result,ic,FALSE);
12838         pic16_aopOp(right,ic,FALSE) ;
12839
12840         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12841
12842
12843         /* if the result is a bit */
12844         if (AOP_TYPE(result) == AOP_CRY) {
12845         
12846                 /* if the right size is a literal then
12847                  * we know what the value is */
12848                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12849
12850                 if (AOP_TYPE(right) == AOP_LIT) {
12851                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12852                                 pic16_popGet(AOP(result),0));
12853
12854                         if (((int) operandLitValue(right))) 
12855                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12856                                         AOP(result)->aopu.aop_dir,
12857                                         AOP(result)->aopu.aop_dir);
12858                         else
12859                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12860                                         AOP(result)->aopu.aop_dir,
12861                                         AOP(result)->aopu.aop_dir);
12862                         goto release;
12863                 }
12864
12865                 /* the right is also a bit variable */
12866                 if (AOP_TYPE(right) == AOP_CRY) {
12867                         emitCLRC;
12868                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12869
12870                         pic16_emitcode("clrc","");
12871                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12872                                 AOP(right)->aopu.aop_dir,
12873                                 AOP(right)->aopu.aop_dir);
12874                         pic16_aopPut(AOP(result),"c",0);
12875                         goto release ;
12876                 }
12877
12878                 /* we need to or */
12879                 if (AOP_TYPE(right) == AOP_REG) {
12880                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12881                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12882                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12883                 }
12884                 pic16_toBoolean(right);
12885                 pic16_aopPut(AOP(result),"a",0);
12886                 goto release ;
12887         }
12888
12889         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12890           int offset = 1;
12891
12892                 size = AOP_SIZE(result);
12893
12894                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12895
12896                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12897                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12898                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12899
12900                 while (size--)
12901                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12902
12903                 goto release;
12904         }
12905
12906         if(IS_BITFIELD(getSpec(restype))
12907           && IS_BITFIELD(getSpec(rtype))) {
12908           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12909         }
12910         
12911         /* port from pic14 to cope with generic pointers */
12912         if (PIC_IS_TAGGED(restype))
12913         {
12914           operand *result = IC_RESULT(ic);
12915           //operand *left = IC_LEFT(ic);
12916           operand *right = IC_RIGHT(ic);
12917           int tag = 0xff;
12918
12919           /* copy common part */
12920           int max, size = AOP_SIZE(result);
12921           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12922           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12923
12924           max = size;
12925           while (size--)
12926           {
12927             pic16_mov2w (AOP(right), size);
12928             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12929           } // while
12930
12931           /* upcast into generic pointer type? */
12932           if (IS_GENPTR(restype)
12933               && !PIC_IS_TAGGED(rtype)
12934               && (AOP_SIZE(result) > max))
12935           {
12936             /* determine appropriate tag for right */
12937             if (PIC_IS_DATA_PTR(rtype))
12938               tag = GPTR_TAG_DATA;
12939             else if (IS_CODEPTR(rtype))
12940               tag = GPTR_TAG_CODE;
12941             else if (PIC_IS_DATA_PTR(ctype)) {
12942               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12943               tag = GPTR_TAG_DATA;
12944             } else if (IS_CODEPTR(ctype)) {
12945               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12946               tag = GPTR_TAG_CODE;
12947             } else if (IS_PTR(rtype)) {
12948               PERFORM_ONCE(weirdcast,
12949               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12950               );
12951               tag = GPTR_TAG_DATA;
12952             } else {
12953               PERFORM_ONCE(weirdcast,
12954               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12955               );
12956               tag = GPTR_TAG_DATA;
12957             }
12958
12959             assert (AOP_SIZE(result) == 3);
12960             /* zero-extend address... */
12961             for (size = max; size < AOP_SIZE(result)-1; size++)
12962               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12963             /* ...and add tag */
12964             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12965           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12966             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12967             for (size = max; size < AOP_SIZE(result)-1; size++)
12968               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12969             /* add __code tag */
12970             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12971           } else if (AOP_SIZE(result) > max) {
12972             /* extend non-pointers */
12973             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12974             pic16_addSign(result, max, 0);
12975           } // if
12976           goto release;
12977         }
12978
12979         /* if they are the same size : or less */
12980         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12981
12982                 /* if they are in the same place */
12983                 if (pic16_sameRegs(AOP(right),AOP(result)))
12984                         goto release;
12985
12986                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12987 #if 0
12988                 if (IS_PTR_CONST(rtype))
12989 #else
12990                 if (IS_CODEPTR(rtype))
12991 #endif
12992                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12993
12994 #if 0
12995                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12996 #else
12997                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12998 #endif
12999                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13000
13001 #if 0
13002                 if(AOP_TYPE(right) == AOP_IMMD) {
13003                   pCodeOp *pcop0, *pcop1, *pcop2;
13004                   symbol *sym = OP_SYMBOL( right );
13005
13006                         size = AOP_SIZE(result);
13007                         /* low */
13008                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13009                         /* high */
13010                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13011                         /* upper */
13012                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13013         
13014                         if (size == 3) {
13015                                 pic16_emitpcode(POC_MOVLW, pcop0);
13016                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13017                                 pic16_emitpcode(POC_MOVLW, pcop1);
13018                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13019                                 pic16_emitpcode(POC_MOVLW, pcop2);
13020                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13021                         } else
13022                         if (size == 2) {
13023                                 pic16_emitpcode(POC_MOVLW, pcop0);
13024                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13025                                 pic16_emitpcode(POC_MOVLW, pcop1);
13026                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13027                         } else {
13028                                 pic16_emitpcode(POC_MOVLW, pcop0);
13029                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13030                         }
13031                 } else
13032 #endif
13033                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13034                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13035                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13036                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13037                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13038                         if(AOP_SIZE(result) <2)
13039                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13040                 } else {
13041                         /* if they in different places then copy */
13042                         size = AOP_SIZE(result);
13043                         offset = 0 ;
13044                         while (size--) {
13045                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13046                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13047                                 offset++;
13048                         }
13049                 }
13050                 goto release;
13051         }
13052
13053         /* if the result is of type pointer */
13054         if (IS_PTR(ctype)) {
13055           int p_type;
13056           sym_link *type = operandType(right);
13057           sym_link *etype = getSpec(type);
13058
13059                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13060
13061                 /* pointer to generic pointer */
13062                 if (IS_GENPTR(ctype)) {
13063                   char *l = zero;
13064             
13065                         if (IS_PTR(type)) 
13066                                 p_type = DCL_TYPE(type);
13067                         else {
13068                 /* we have to go by the storage class */
13069                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13070
13071 /*              if (SPEC_OCLS(etype)->codesp )  */
13072 /*                  p_type = CPOINTER ;  */
13073 /*              else */
13074 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13075 /*                      p_type = FPOINTER ; */
13076 /*                  else */
13077 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13078 /*                          p_type = PPOINTER; */
13079 /*                      else */
13080 /*                          if (SPEC_OCLS(etype) == idata ) */
13081 /*                              p_type = IPOINTER ; */
13082 /*                          else */
13083 /*                              p_type = POINTER ; */
13084             }
13085                 
13086             /* the first two bytes are known */
13087       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13088             size = GPTRSIZE - 1; 
13089             offset = 0 ;
13090             while (size--) {
13091               if(offset < AOP_SIZE(right)) {
13092                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13093                 pic16_mov2f(AOP(result), AOP(right), offset);
13094 /*
13095                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13096                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13097                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13098                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13099                 } else { 
13100                   
13101                   pic16_aopPut(AOP(result),
13102                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13103                          offset);
13104                 }
13105 */
13106               } else 
13107                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13108               offset++;
13109             }
13110             /* the last byte depending on type */
13111             switch (p_type) {
13112             case IPOINTER:
13113             case POINTER:
13114             case FPOINTER:
13115                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13116                 break;
13117
13118             case CPOINTER:
13119                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13120                 break;
13121
13122             case PPOINTER:
13123               pic16_emitcode(";BUG!? ","%d",__LINE__);
13124                 l = "#0x03";
13125                 break;
13126
13127             case GPOINTER:
13128                 if (GPTRSIZE > AOP_SIZE(right)) {
13129                   // assume __data pointer... THIS MIGHT BE WRONG!
13130                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13131                 } else {
13132                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13133                 }
13134               break;
13135               
13136             default:
13137                 /* this should never happen */
13138                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13139                        "got unknown pointer type");
13140                 exit(1);
13141             }
13142             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13143             goto release ;
13144         }
13145         
13146         
13147         assert( 0 );
13148         /* just copy the pointers */
13149         size = AOP_SIZE(result);
13150         offset = 0 ;
13151         while (size--) {
13152             pic16_aopPut(AOP(result),
13153                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13154                    offset);
13155             offset++;
13156         }
13157         goto release ;
13158     }
13159     
13160
13161
13162     /* so we now know that the size of destination is greater
13163     than the size of the source.
13164     Now, if the next iCode is an operator then we might be
13165     able to optimize the operation without performing a cast.
13166     */
13167     if(genMixedOperation(ic))
13168       goto release;
13169
13170     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13171     
13172     /* we move to result for the size of source */
13173     size = AOP_SIZE(right);
13174     offset = 0 ;
13175
13176     while (size--) {
13177       if(!_G.resDirect)
13178         pic16_mov2f(AOP(result), AOP(right), offset);
13179       offset++;
13180     }
13181
13182     /* now depending on the sign of the destination */
13183     size = AOP_SIZE(result) - AOP_SIZE(right);
13184     /* if unsigned or not an integral type */
13185     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13186       while (size--)
13187         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13188     } else {
13189       /* we need to extend the sign :( */
13190
13191       if(size == 1) {
13192         /* Save one instruction of casting char to int */
13193         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13194         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13195         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13196       } else {
13197         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13198
13199         if(offset)
13200           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13201         else
13202           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13203         
13204         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13205
13206         while (size--)
13207           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13208       }
13209     }
13210
13211 release:
13212     pic16_freeAsmop(right,NULL,ic,TRUE);
13213     pic16_freeAsmop(result,NULL,ic,TRUE);
13214
13215 }
13216
13217 /*-----------------------------------------------------------------*/
13218 /* genDjnz - generate decrement & jump if not zero instrucion      */
13219 /*-----------------------------------------------------------------*/
13220 static int genDjnz (iCode *ic, iCode *ifx)
13221 {
13222     symbol *lbl, *lbl1;
13223     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13224
13225     if (!ifx)
13226         return 0;
13227     
13228     /* if the if condition has a false label
13229        then we cannot save */
13230     if (IC_FALSE(ifx))
13231         return 0;
13232
13233     /* if the minus is not of the form 
13234        a = a - 1 */
13235     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13236         !IS_OP_LITERAL(IC_RIGHT(ic)))
13237         return 0;
13238
13239     if (operandLitValue(IC_RIGHT(ic)) != 1)
13240         return 0;
13241
13242     /* if the size of this greater than one then no
13243        saving */
13244     if (getSize(operandType(IC_RESULT(ic))) > 1)
13245         return 0;
13246
13247     /* otherwise we can save BIG */
13248     lbl = newiTempLabel(NULL);
13249     lbl1= newiTempLabel(NULL);
13250
13251     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13252     
13253     if (IS_AOP_PREG(IC_RESULT(ic))) {
13254         pic16_emitcode("dec","%s",
13255                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13256         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13257         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13258     } else {    
13259
13260
13261       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13262       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13263
13264       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13265       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13266
13267     }
13268     
13269     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13270     ifx->generated = 1;
13271     return 1;
13272 }
13273
13274 /*-----------------------------------------------------------------*/
13275 /* genReceive - generate code for a receive iCode                  */
13276 /*-----------------------------------------------------------------*/
13277 static void genReceive (iCode *ic)
13278 {    
13279
13280   FENTRY;
13281
13282 #if 0
13283   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13284         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13285 #endif
13286 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13287
13288   if (isOperandInFarSpace(IC_RESULT(ic))
13289       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13290           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13291
13292     int size = getSize(operandType(IC_RESULT(ic)));
13293     int offset =  pic16_fReturnSizePic - size;
13294
13295       assert( 0 );
13296       while (size--) {
13297         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13298                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13299                       offset++;
13300         }
13301
13302       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13303
13304       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13305       size = AOP_SIZE(IC_RESULT(ic));
13306       offset = 0;
13307       while (size--) {
13308         pic16_emitcode ("pop","acc");
13309         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13310       }
13311   } else {
13312     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13313     _G.accInUse++;
13314     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13315     _G.accInUse--;
13316
13317     /* set pseudo stack pointer to where it should be - dw*/
13318     GpsuedoStkPtr = ic->parmBytes;
13319
13320     /* setting GpsuedoStkPtr has side effects here: */
13321     assignResultValue(IC_RESULT(ic), 0);
13322   }
13323
13324   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13325 }
13326
13327 /*-----------------------------------------------------------------*/
13328 /* genDummyRead - generate code for dummy read of volatiles        */
13329 /*-----------------------------------------------------------------*/
13330 static void
13331 genDummyRead (iCode * ic)
13332 {
13333   operand *op;
13334   int i;
13335
13336   op = IC_RIGHT(ic);
13337   if (op && IS_SYMOP(op)) {
13338     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13339       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13340       return;
13341     }
13342     pic16_aopOp (op, ic, FALSE);
13343     for (i=0; i < AOP_SIZE(op); i++) {
13344       // may need to protect this from the peepholer -- this is not nice but works...
13345       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13346       pic16_mov2w (AOP(op),i);
13347       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13348     } // for i
13349     pic16_freeAsmop (op, NULL, ic, TRUE);
13350   } else if (op) {
13351     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13352   } // if
13353 }
13354
13355 /*-----------------------------------------------------------------*/
13356 /* genpic16Code - generate code for pic16 based controllers        */
13357 /*-----------------------------------------------------------------*/
13358 /*
13359  * At this point, ralloc.c has gone through the iCode and attempted
13360  * to optimize in a way suitable for a PIC. Now we've got to generate
13361  * PIC instructions that correspond to the iCode.
13362  *
13363  * Once the instructions are generated, we'll pass through both the
13364  * peep hole optimizer and the pCode optimizer.
13365  *-----------------------------------------------------------------*/
13366
13367 void genpic16Code (iCode *lic)
13368 {
13369   iCode *ic;
13370   int cln = 0;
13371
13372     lineHead = lineCurr = NULL;
13373
13374     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13375     pic16_addpBlock(pb);
13376
13377 #if 0
13378     /* if debug information required */
13379     if (options.debug && currFunc) {
13380       if (currFunc) {
13381         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13382       }
13383     }
13384 #endif
13385
13386     for (ic = lic ; ic ; ic = ic->next ) {
13387
13388       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13389       if ( cln != ic->lineno ) {
13390         if ( options.debug ) {
13391           debugFile->writeCLine (ic);
13392         }
13393         
13394         if(!options.noCcodeInAsm) {
13395           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13396               printCLine(ic->filename, ic->lineno)));
13397         }
13398
13399         cln = ic->lineno ;
13400       }
13401         
13402       if(options.iCodeInAsm) {
13403         char *l;
13404
13405           /* insert here code to print iCode as comment */
13406           l = Safe_strdup(printILine(ic));
13407           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13408       }
13409
13410       /* if the result is marked as
13411        * spilt and rematerializable or code for
13412        * this has already been generated then
13413        * do nothing */
13414       if (resultRemat(ic) || ic->generated ) 
13415         continue ;
13416         
13417       /* depending on the operation */
13418       switch (ic->op) {
13419         case '!' :
13420           pic16_genNot(ic);
13421           break;
13422             
13423         case '~' :
13424           pic16_genCpl(ic);
13425           break;
13426             
13427         case UNARYMINUS:
13428           genUminus (ic);
13429           break;
13430             
13431         case IPUSH:
13432           genIpush (ic);
13433           break;
13434             
13435         case IPOP:
13436           /* IPOP happens only when trying to restore a 
13437            * spilt live range, if there is an ifx statement
13438            * following this pop then the if statement might
13439            * be using some of the registers being popped which
13440            * would destroy the contents of the register so
13441            * we need to check for this condition and handle it */
13442            if (ic->next
13443              && ic->next->op == IFX
13444              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13445                genIfx (ic->next,ic);
13446           else
13447             genIpop (ic);
13448           break; 
13449             
13450         case CALL:
13451           genCall (ic);
13452           break;
13453             
13454         case PCALL:
13455           genPcall (ic);
13456           break;
13457             
13458         case FUNCTION:
13459           genFunction (ic);
13460           break;
13461             
13462         case ENDFUNCTION:
13463           genEndFunction (ic);
13464           break;
13465             
13466         case RETURN:
13467           genRet (ic);
13468           break;
13469             
13470         case LABEL:
13471           genLabel (ic);
13472           break;
13473             
13474         case GOTO:
13475           genGoto (ic);
13476           break;
13477             
13478         case '+' :
13479           pic16_genPlus (ic) ;
13480           break;
13481             
13482         case '-' :
13483           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13484             pic16_genMinus (ic);
13485           break;
13486
13487         case '*' :
13488           genMult (ic);
13489           break;
13490             
13491         case '/' :
13492           genDiv (ic) ;
13493           break;
13494             
13495         case '%' :
13496           genMod (ic);
13497           break;
13498             
13499         case '>' :
13500           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13501           break;
13502             
13503         case '<' :
13504           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13505           break;
13506             
13507         case LE_OP:
13508         case GE_OP:
13509         case NE_OP:
13510           /* note these two are xlated by algebraic equivalence
13511            * during parsing SDCC.y */
13512           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13513             "got '>=' or '<=' shouldn't have come here");
13514           break;
13515
13516         case EQ_OP:
13517           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13518           break;            
13519             
13520         case AND_OP:
13521           genAndOp (ic);
13522           break;
13523             
13524         case OR_OP:
13525           genOrOp (ic);
13526           break;
13527             
13528         case '^' :
13529           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13530           break;
13531             
13532         case '|' :
13533           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13534           break;
13535             
13536         case BITWISEAND:
13537           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13538           break;
13539             
13540         case INLINEASM:
13541           genInline (ic);
13542           break;
13543             
13544         case RRC:
13545           genRRC (ic);
13546           break;
13547             
13548         case RLC:
13549           genRLC (ic);
13550           break;
13551             
13552         case GETHBIT:
13553           genGetHbit (ic);
13554           break;
13555             
13556         case LEFT_OP:
13557           genLeftShift (ic);
13558           break;
13559             
13560         case RIGHT_OP:
13561           genRightShift (ic);
13562           break;
13563             
13564         case GET_VALUE_AT_ADDRESS:
13565           genPointerGet(ic);
13566           break;
13567             
13568         case '=' :
13569           if (POINTER_SET(ic))
13570             genPointerSet(ic);
13571           else
13572             genAssign(ic);
13573           break;
13574             
13575         case IFX:
13576           genIfx (ic,NULL);
13577           break;
13578             
13579         case ADDRESS_OF:
13580           genAddrOf (ic);
13581           break;
13582             
13583         case JUMPTABLE:
13584           genJumpTab (ic);
13585           break;
13586             
13587         case CAST:
13588           genCast (ic);
13589           break;
13590             
13591         case RECEIVE:
13592           genReceive(ic);
13593           break;
13594             
13595         case SEND:
13596           addSet(&_G.sendSet,ic);
13597           break;
13598
13599         case DUMMY_READ_VOLATILE:
13600           genDummyRead (ic);
13601           break;
13602
13603         default :
13604           ic = ic;
13605       }
13606     }
13607
13608
13609     /* now we are ready to call the
13610        peep hole optimizer */
13611     if (!options.nopeep)
13612       peepHole (&lineHead);
13613
13614     /* now do the actual printing */
13615     printLine (lineHead, codeOutFile);
13616
13617 #ifdef PCODE_DEBUG
13618     DFPRINTF((stderr,"printing pBlock\n\n"));
13619     pic16_printpBlock(stdout,pb);
13620 #endif
13621
13622     return;
13623 }
13624