* src/avr/gen.c (aopop),
[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         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3777         if(STACK_MODEL_LARGE)
3778           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 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         if(STACK_MODEL_LARGE)
3932           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3933         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
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(is_LitOp(op)) {
4016       pic16_movLit2f(dest, lit);
4017     } else {
4018       if(dest->type == PO_WREG && (offset == 0)) {
4019         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4020       return;
4021     }
4022     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4023   }
4024 }
4025
4026 /*-----------------------------------------------------------------*/
4027 /* genRet - generate code for return statement                     */
4028 /*-----------------------------------------------------------------*/
4029 static void genRet (iCode *ic)
4030 {
4031   int size;
4032   operand *left;
4033
4034     FENTRY;
4035         /* if we have no return value then
4036          * just generate the "ret" */
4037         
4038         if (!IC_LEFT(ic)) 
4039                 goto jumpret;       
4040     
4041         /* we have something to return then
4042          * move the return value into place */
4043         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4044         size = AOP_SIZE(IC_LEFT(ic));
4045
4046         if(size <= 4) {
4047           if(size>3)
4048             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4049           
4050           if(size>2)
4051             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4052
4053           if(size>1)
4054             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4055           
4056           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4057
4058         } else {
4059                 /* >32-bits, setup stack and FSR0 */
4060                 while (size--) {
4061 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4062 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4063
4064                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4065
4066 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4067                         GpsuedoStkPtr++;
4068                 }
4069                         
4070                 /* setup FSR0 */
4071                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4073
4074                 if(STACK_MODEL_LARGE) {
4075                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4076                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4077                 } else {
4078                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4079                 }
4080         }
4081                                 
4082 #if 0
4083         /* old code, left here for reference -- VR */    
4084         while (size--) {
4085           char *l ;
4086
4087                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4088                         /* #NOCHANGE */
4089                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4090                         pic16_emitpcomment("push %s",l);
4091                         pushed++;
4092                 } else {
4093                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4094                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4095                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4096                         
4097                         if (strcmp(fReturn[offset],l)) {
4098                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4099                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4100                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4101                                 } else {
4102                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4103                                 }
4104                                 
4105                                 if(size) {
4106                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4107                                 }
4108                                 offset++;
4109                         }
4110                 }
4111         }    
4112
4113         if (pushed) {
4114                 while(pushed) {
4115                         pushed--;
4116                         if (strcmp(fReturn[pushed],"a"))
4117                                 pic16_emitcode("pop",fReturn[pushed]);
4118                         else
4119                                 pic16_emitcode("pop","acc");
4120                 }
4121         }
4122 #endif
4123
4124
4125         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4126     
4127 jumpret:
4128         /* generate a jump to the return label
4129          * if the next is not the return statement */
4130         if (!(ic->next && ic->next->op == LABEL
4131                 && IC_LABEL(ic->next) == returnLabel)) {
4132         
4133                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4134                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4135         }
4136 }
4137
4138 /*-----------------------------------------------------------------*/
4139 /* genLabel - generates a label                                    */
4140 /*-----------------------------------------------------------------*/
4141 static void genLabel (iCode *ic)
4142 {
4143   FENTRY;
4144
4145   /* special case never generate */
4146   if (IC_LABEL(ic) == entryLabel)
4147     return ;
4148
4149   pic16_emitpLabel(IC_LABEL(ic)->key);
4150 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a goto                                      */
4155 /*-----------------------------------------------------------------*/
4156 //tsd
4157 static void genGoto (iCode *ic)
4158 {
4159   FENTRY;
4160   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4161 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4162 }
4163
4164
4165 /*-----------------------------------------------------------------*/
4166 /* genMultbits :- multiplication of bits                           */
4167 /*-----------------------------------------------------------------*/
4168 static void genMultbits (operand *left, 
4169                          operand *right, 
4170                          operand *result)
4171 {
4172   FENTRY;
4173
4174   if(!pic16_sameRegs(AOP(result),AOP(right)))
4175     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4176
4177   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4178   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4179   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4180
4181 }
4182
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneByte : 8 bit multiplication & division                */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneByte (operand *left,
4188                             operand *right,
4189                             operand *result)
4190 {
4191
4192   FENTRY;
4193   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4194   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4195
4196   /* (if two literals, the value is computed before) */
4197   /* if one literal, literal on the right */
4198   if (AOP_TYPE(left) == AOP_LIT){
4199     operand *t = right;
4200     right = left;
4201     left = t;
4202   }
4203
4204         /* size is already checked in genMult == 1 */
4205 //      size = AOP_SIZE(result);
4206
4207         if (AOP_TYPE(right) == AOP_LIT){
4208                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4209                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4210                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4211                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212         } else {
4213                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4214                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4215                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4216                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4217         }
4218         
4219         pic16_genMult8X8_8 (left, right,result);
4220 }
4221
4222 /*-----------------------------------------------------------------*/
4223 /* genMultOneWord : 16 bit multiplication                          */
4224 /*-----------------------------------------------------------------*/
4225 static void genMultOneWord (operand *left,
4226                             operand *right,
4227                             operand *result)
4228 {
4229   FENTRY;
4230   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4231   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4232
4233   /* (if two literals, the value is computed before)
4234    * if one literal, literal on the right */
4235   if (AOP_TYPE(left) == AOP_LIT){
4236     operand *t = right;
4237     right = left;
4238     left = t;
4239   }
4240
4241   /* size is checked already == 2 */
4242 //  size = AOP_SIZE(result);
4243
4244   if (AOP_TYPE(right) == AOP_LIT) {
4245     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4246       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4247       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4248       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4249   } else {
4250     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4251       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4252       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4253       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4254   }
4255         
4256   pic16_genMult16X16_16(left, right,result);
4257 }
4258
4259 /*-----------------------------------------------------------------*/
4260 /* genMultOneLong : 32 bit multiplication                          */
4261 /*-----------------------------------------------------------------*/
4262 static void genMultOneLong (operand *left,
4263                             operand *right,
4264                             operand *result)
4265 {
4266   FENTRY;
4267   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4268   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4269
4270   /* (if two literals, the value is computed before)
4271    * if one literal, literal on the right */
4272   if (AOP_TYPE(left) == AOP_LIT){
4273     operand *t = right;
4274     right = left;
4275     left = t;
4276   }
4277
4278   /* size is checked already == 4 */
4279 //  size = AOP_SIZE(result);
4280
4281   if (AOP_TYPE(right) == AOP_LIT) {
4282     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4283         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4284         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4285         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4286   } else {
4287     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4288         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4289         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4290         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4291   }
4292         
4293   pic16_genMult32X32_32(left, right,result);
4294 }
4295
4296
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genMult - generates code for multiplication                     */
4300 /*-----------------------------------------------------------------*/
4301 static void genMult (iCode *ic)
4302 {
4303   operand *left = IC_LEFT(ic);
4304   operand *right = IC_RIGHT(ic);
4305   operand *result= IC_RESULT(ic);   
4306
4307     FENTRY;
4308         /* assign the amsops */
4309         pic16_aopOp (left,ic,FALSE);
4310         pic16_aopOp (right,ic,FALSE);
4311         pic16_aopOp (result,ic,TRUE);
4312
4313         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4314
4315         /* special cases first *
4316         * both are bits */
4317         if (AOP_TYPE(left) == AOP_CRY
4318                 && AOP_TYPE(right)== AOP_CRY) {
4319                 genMultbits(left,right,result);
4320           goto release ;
4321         }
4322
4323         /* if both are of size == 1 */
4324         if(AOP_SIZE(left) == 1
4325                 && AOP_SIZE(right) == 1) {
4326                 genMultOneByte(left,right,result);
4327           goto release ;
4328         }
4329
4330         /* if both are of size == 2 */
4331         if(AOP_SIZE(left) == 2
4332                 && AOP_SIZE(right) == 2) {
4333                 genMultOneWord(left, right, result);
4334           goto release;
4335         }
4336         
4337         /* if both are of size == 4 */
4338         if(AOP_SIZE(left) == 4
4339                 && AOP_SIZE(right) == 4) {
4340                 genMultOneLong(left, right, result);
4341           goto release;
4342         }
4343         
4344         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4345
4346
4347         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4348         /* should have been converted to function call */
4349         assert(0) ;
4350
4351 release :
4352         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354         pic16_freeAsmop(result,NULL,ic,TRUE); 
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genDivbits :- division of bits                                  */
4359 /*-----------------------------------------------------------------*/
4360 static void genDivbits (operand *left, 
4361                         operand *right, 
4362                         operand *result)
4363 {
4364   char *l;
4365
4366     FENTRY;
4367     /* the result must be bit */    
4368     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4369     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4370
4371     MOVA(l);    
4372
4373     pic16_emitcode("div","ab");
4374     pic16_emitcode("rrc","a");
4375     pic16_aopPut(AOP(result),"c",0);
4376 }
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genDivOneByte : 8 bit division                                  */
4380 /*-----------------------------------------------------------------*/
4381 static void genDivOneByte (operand *left,
4382                            operand *right,
4383                            operand *result)
4384 {
4385   sym_link *opetype = operandType(result);
4386   char *l ;
4387   symbol *lbl ;
4388   int size,offset;
4389
4390         /* result = divident / divisor
4391          * - divident may be a register or a literal,
4392          * - divisor may be a register or a literal,
4393          * so there are 3 cases (literal / literal is optimized
4394          * by the front-end) to handle.
4395          * In addition we must handle signed and unsigned, which
4396          * result in 6 final different cases -- VR */
4397
4398     FENTRY;
4399     
4400     size = AOP_SIZE(result) - 1;
4401     offset = 1;
4402     /* signed or unsigned */
4403     if (SPEC_USIGN(opetype)) {
4404       pCodeOp *pct1,    /* count */
4405                 *pct2,  /* reste */
4406                 *pct3;  /* temp */
4407       symbol *label1, *label2, *label3;;
4408
4409
4410         /* unsigned is easy */
4411
4412         pct1 = pic16_popGetTempReg(1);
4413         pct2 = pic16_popGetTempReg(1);
4414         pct3 = pic16_popGetTempReg(1);
4415         
4416         label1 = newiTempLabel(NULL);
4417         label2 = newiTempLabel(NULL);
4418         label3 = newiTempLabel(NULL);
4419
4420         /* the following algorithm is extracted from divuint.c */
4421
4422         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4423         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4424         
4425         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4426
4427         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4428         
4429         pic16_emitpLabel(label1->key);
4430         
4431         emitCLRC;
4432         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4433
4434
4435         emitCLRC;
4436         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4437         
4438
4439         emitSKPNC;
4440         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4441         
4442         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4443         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4444         
4445         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4446         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4447         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4448         
4449         pic16_emitpLabel( label3->key );
4450         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4451         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4452         
4453         
4454
4455         pic16_emitpLabel(label2->key);
4456         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4457         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4458         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4459         
4460         /* result is in wreg */
4461         if(AOP_TYPE(result) != AOP_ACC)
4462                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4463
4464         pic16_popReleaseTempReg( pct3, 1);
4465         pic16_popReleaseTempReg( pct2, 1);
4466         pic16_popReleaseTempReg( pct1, 1);
4467
4468         return ;
4469     }
4470
4471     /* signed is a little bit more difficult */
4472
4473     /* save the signs of the operands */
4474     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4475     MOVA(l);    
4476     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4477     pic16_emitcode("push","acc"); /* save it on the stack */
4478
4479     /* now sign adjust for both left & right */
4480     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4481     MOVA(l);       
4482     lbl = newiTempLabel(NULL);
4483     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4484     pic16_emitcode("cpl","a");   
4485     pic16_emitcode("inc","a");
4486     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4487     pic16_emitcode("mov","b,a");
4488
4489     /* sign adjust left side */
4490     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4491     MOVA(l);
4492
4493     lbl = newiTempLabel(NULL);
4494     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4495     pic16_emitcode("cpl","a");
4496     pic16_emitcode("inc","a");
4497     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4498
4499     /* now the division */
4500     pic16_emitcode("div","ab");
4501     /* we are interested in the lower order
4502     only */
4503     pic16_emitcode("mov","b,a");
4504     lbl = newiTempLabel(NULL);
4505     pic16_emitcode("pop","acc");   
4506     /* if there was an over flow we don't 
4507     adjust the sign of the result */
4508     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4509     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4510     CLRC;
4511     pic16_emitcode("clr","a");
4512     pic16_emitcode("subb","a,b");
4513     pic16_emitcode("mov","b,a");
4514     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4515
4516     /* now we are done */
4517     pic16_aopPut(AOP(result),"b",0);
4518     if(size > 0){
4519         pic16_emitcode("mov","c,b.7");
4520         pic16_emitcode("subb","a,acc");   
4521     }
4522     while (size--)
4523         pic16_aopPut(AOP(result),"a",offset++);
4524
4525 }
4526
4527 /*-----------------------------------------------------------------*/
4528 /* genDiv - generates code for division                            */
4529 /*-----------------------------------------------------------------*/
4530 static void genDiv (iCode *ic)
4531 {
4532     operand *left = IC_LEFT(ic);
4533     operand *right = IC_RIGHT(ic);
4534     operand *result= IC_RESULT(ic);   
4535
4536
4537         /* Division is a very lengthy algorithm, so it is better
4538          * to call support routines than inlining algorithm.
4539          * Division functions written here just in case someone
4540          * wants to inline and not use the support libraries -- VR */
4541
4542     FENTRY;
4543     
4544     /* assign the amsops */
4545     pic16_aopOp (left,ic,FALSE);
4546     pic16_aopOp (right,ic,FALSE);
4547     pic16_aopOp (result,ic,TRUE);
4548
4549     /* special cases first */
4550     /* both are bits */
4551     if (AOP_TYPE(left) == AOP_CRY &&
4552         AOP_TYPE(right)== AOP_CRY) {
4553         genDivbits(left,right,result);
4554         goto release ;
4555     }
4556
4557     /* if both are of size == 1 */
4558     if (AOP_SIZE(left) == 1 &&
4559         AOP_SIZE(right) == 1 ) {
4560         genDivOneByte(left,right,result);
4561         goto release ;
4562     }
4563
4564     /* should have been converted to function call */
4565     assert(0);
4566 release :
4567     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4568     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569     pic16_freeAsmop(result,NULL,ic,TRUE); 
4570 }
4571
4572 /*-----------------------------------------------------------------*/
4573 /* genModbits :- modulus of bits                                   */
4574 /*-----------------------------------------------------------------*/
4575 static void genModbits (operand *left, 
4576                         operand *right, 
4577                         operand *result)
4578 {
4579   char *l;
4580
4581     FENTRY;  
4582     
4583     werror(W_POSSBUG2, __FILE__, __LINE__);
4584     /* the result must be bit */    
4585     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4586     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4587
4588     MOVA(l);       
4589
4590     pic16_emitcode("div","ab");
4591     pic16_emitcode("mov","a,b");
4592     pic16_emitcode("rrc","a");
4593     pic16_aopPut(AOP(result),"c",0);
4594 }
4595
4596 /*-----------------------------------------------------------------*/
4597 /* genModOneByte : 8 bit modulus                                   */
4598 /*-----------------------------------------------------------------*/
4599 static void genModOneByte (operand *left,
4600                            operand *right,
4601                            operand *result)
4602 {
4603   sym_link *opetype = operandType(result);
4604   char *l ;
4605   symbol *lbl ;
4606
4607     FENTRY;
4608     werror(W_POSSBUG2, __FILE__, __LINE__);
4609
4610     /* signed or unsigned */
4611     if (SPEC_USIGN(opetype)) {
4612         /* unsigned is easy */
4613         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4614         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4615         MOVA(l);    
4616         pic16_emitcode("div","ab");
4617         pic16_aopPut(AOP(result),"b",0);
4618         return ;
4619     }
4620
4621     /* signed is a little bit more difficult */
4622
4623     /* save the signs of the operands */
4624     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4625     MOVA(l);
4626
4627     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4628     pic16_emitcode("push","acc"); /* save it on the stack */
4629
4630     /* now sign adjust for both left & right */
4631     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4632     MOVA(l);
4633
4634     lbl = newiTempLabel(NULL);
4635     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4636     pic16_emitcode("cpl","a");   
4637     pic16_emitcode("inc","a");
4638     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4639     pic16_emitcode("mov","b,a"); 
4640
4641     /* sign adjust left side */
4642     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4643     MOVA(l);
4644
4645     lbl = newiTempLabel(NULL);
4646     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4647     pic16_emitcode("cpl","a");   
4648     pic16_emitcode("inc","a");
4649     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4650
4651     /* now the multiplication */
4652     pic16_emitcode("div","ab");
4653     /* we are interested in the lower order
4654     only */
4655     lbl = newiTempLabel(NULL);
4656     pic16_emitcode("pop","acc");   
4657     /* if there was an over flow we don't 
4658     adjust the sign of the result */
4659     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4660     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4661     CLRC ;
4662     pic16_emitcode("clr","a");
4663     pic16_emitcode("subb","a,b");
4664     pic16_emitcode("mov","b,a");
4665     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4666
4667     /* now we are done */
4668     pic16_aopPut(AOP(result),"b",0);
4669
4670 }
4671
4672 /*-----------------------------------------------------------------*/
4673 /* genMod - generates code for division                            */
4674 /*-----------------------------------------------------------------*/
4675 static void genMod (iCode *ic)
4676 {
4677   operand *left = IC_LEFT(ic);
4678   operand *right = IC_RIGHT(ic);
4679   operand *result= IC_RESULT(ic);  
4680
4681     FENTRY;
4682     
4683     /* assign the amsops */
4684     pic16_aopOp (left,ic,FALSE);
4685     pic16_aopOp (right,ic,FALSE);
4686     pic16_aopOp (result,ic,TRUE);
4687
4688     /* special cases first */
4689     /* both are bits */
4690     if (AOP_TYPE(left) == AOP_CRY &&
4691         AOP_TYPE(right)== AOP_CRY) {
4692         genModbits(left,right,result);
4693         goto release ;
4694     }
4695
4696     /* if both are of size == 1 */
4697     if (AOP_SIZE(left) == 1 &&
4698         AOP_SIZE(right) == 1 ) {
4699         genModOneByte(left,right,result);
4700         goto release ;
4701     }
4702
4703     /* should have been converted to function call */
4704     assert(0);
4705
4706 release :
4707     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4708     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709     pic16_freeAsmop(result,NULL,ic,TRUE); 
4710 }
4711
4712 /*-----------------------------------------------------------------*/
4713 /* genIfxJump :- will create a jump depending on the ifx           */
4714 /*-----------------------------------------------------------------*/
4715 /*
4716   note: May need to add parameter to indicate when a variable is in bit space.
4717 */
4718 static void genIfxJump (iCode *ic, char *jval)
4719 {
4720   FENTRY;
4721   
4722     /* if true label then we jump if condition
4723     supplied is true */
4724     if ( IC_TRUE(ic) ) {
4725
4726         if(strcmp(jval,"a") == 0)
4727           emitSKPZ;
4728         else if (strcmp(jval,"c") == 0)
4729           emitSKPNC;
4730         else {
4731           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4732           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4733         }
4734
4735         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4736         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4737
4738     }
4739     else {
4740         /* false label is present */
4741         if(strcmp(jval,"a") == 0)
4742           emitSKPNZ;
4743         else if (strcmp(jval,"c") == 0)
4744           emitSKPC;
4745         else {
4746           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4747           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4748         }
4749
4750         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4751         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4752
4753     }
4754
4755
4756     /* mark the icode as generated */
4757     ic->generated = 1;
4758 }
4759
4760 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4761 {
4762   FENTRY;
4763   
4764     /* if true label then we jump if condition
4765     supplied is true */
4766     if ( IC_TRUE(ic) ) {
4767       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4768       pic16_emitpcode(POC_BTFSC, jop);
4769
4770       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4771       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4772
4773     } else {
4774       /* false label is present */
4775       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4776       pic16_emitpcode(POC_BTFSS, jop);
4777           
4778       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4779       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4780     }
4781
4782
4783     /* mark the icode as generated */
4784     ic->generated = 1;
4785 }
4786
4787 #if 0
4788 // not needed ATM
4789
4790 /*-----------------------------------------------------------------*/
4791 /* genSkip                                                         */
4792 /*-----------------------------------------------------------------*/
4793 static void genSkip(iCode *ifx,int status_bit)
4794 {
4795   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4796   if(!ifx)
4797     return;
4798
4799   if ( IC_TRUE(ifx) ) {
4800     switch(status_bit) {
4801     case 'z':
4802       emitSKPNZ;
4803       break;
4804
4805     case 'c':
4806       emitSKPNC;
4807       break;
4808
4809     case 'd':
4810       emitSKPDC;
4811       break;
4812
4813     }
4814
4815     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4816     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4817
4818   } else {
4819
4820     switch(status_bit) {
4821
4822     case 'z':
4823       emitSKPZ;
4824       break;
4825
4826     case 'c':
4827       emitSKPC;
4828       break;
4829
4830     case 'd':
4831       emitSKPDC;
4832       break;
4833     }
4834     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4835     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4836
4837   }
4838
4839 }
4840 #endif
4841
4842 /*-----------------------------------------------------------------*/
4843 /* genSkipc                                                        */
4844 /*-----------------------------------------------------------------*/
4845 static void genSkipc(resolvedIfx *rifx)
4846 {
4847   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4848   
4849   if(!rifx)
4850     return;
4851
4852   if(rifx->condition)
4853     emitSKPNC;
4854   else
4855     emitSKPC;
4856
4857   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4858   rifx->generated = 1;
4859 }
4860
4861 #if !(USE_SIMPLE_GENCMP)
4862 /*-----------------------------------------------------------------*/
4863 /* genSkipz2                                                       */
4864 /*-----------------------------------------------------------------*/
4865 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4866 {
4867   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4868   
4869   if(!rifx)
4870     return;
4871
4872   if( (rifx->condition ^ invert_condition) & 1)
4873     emitSKPZ;
4874   else
4875     emitSKPNZ;
4876
4877   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4878   rifx->generated = 1;
4879 }
4880 #endif
4881
4882 #if 0
4883 /*-----------------------------------------------------------------*/
4884 /* genSkipz                                                        */
4885 /*-----------------------------------------------------------------*/
4886 static void genSkipz(iCode *ifx, int condition)
4887 {
4888   if(!ifx)
4889     return;
4890
4891   if(condition)
4892     emitSKPNZ;
4893   else
4894     emitSKPZ;
4895
4896   if ( IC_TRUE(ifx) )
4897     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4898   else
4899     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4900
4901   if ( IC_TRUE(ifx) )
4902     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4903   else
4904     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4905
4906 }
4907 #endif
4908
4909 #if !(USE_SIMPLE_GENCMP)
4910 /*-----------------------------------------------------------------*/
4911 /* genSkipCond                                                     */
4912 /*-----------------------------------------------------------------*/
4913 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4914 {
4915   if(!rifx)
4916     return;
4917
4918   if(rifx->condition)
4919     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4920   else
4921     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4922
4923
4924   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4925   rifx->generated = 1;
4926 }
4927 #endif
4928
4929 #if 0
4930 /*-----------------------------------------------------------------*/
4931 /* genChkZeroes :- greater or less than comparison                 */
4932 /*     For each byte in a literal that is zero, inclusive or the   */
4933 /*     the corresponding byte in the operand with W                */
4934 /*     returns true if any of the bytes are zero                   */
4935 /*-----------------------------------------------------------------*/
4936 static int genChkZeroes(operand *op, int lit,  int size)
4937 {
4938
4939   int i;
4940   int flag =1;
4941
4942   while(size--) {
4943     i = (lit >> (size*8)) & 0xff;
4944
4945     if(i==0) {
4946       if(flag) 
4947         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4948       else
4949         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4950       flag = 0;
4951     }
4952   }
4953
4954   return (flag==0);
4955 }
4956 #endif
4957
4958
4959 /*-----------------------------------------------------------------*/
4960 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4961 /*                  aop (if it's NOT a literal) or from lit (if    */
4962 /*                  aop is a literal)                              */
4963 /*-----------------------------------------------------------------*/
4964 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4965   if (aop->type == AOP_LIT) {
4966     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4967   } else {
4968     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4969   }
4970 }
4971
4972 /*-----------------------------------------------------------------*/
4973 /* genCmp :- greater or less than comparison                       */
4974 /*-----------------------------------------------------------------*/
4975
4976 #if USE_SIMPLE_GENCMP           /* { */
4977
4978 /* genCmp performs a left < right comparison, stores
4979  * the outcome in result (if != NULL) and generates
4980  * control flow code for the ifx (if != NULL).
4981  *
4982  * This version leaves in sequences like
4983  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4984  * which should be optmized by the peephole
4985  * optimizer - RN 2005-01-01 */
4986 static void genCmp (operand *left,operand *right,
4987                     operand *result, iCode *ifx, int sign)
4988 {
4989   resolvedIfx rIfx;
4990   int size;
4991   int offs;
4992   symbol *templbl;
4993   operand *dummy;
4994   unsigned long lit;
4995   unsigned long mask;
4996   int performedLt;
4997
4998   FENTRY;
4999   
5000   assert (left && right);
5001   assert (AOP_SIZE(left) == AOP_SIZE(right));
5002
5003   size = AOP_SIZE(right) - 1;
5004   mask = (0x100UL << (size*8)) - 1;
5005   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5006   performedLt = 1;
5007   templbl = NULL;
5008   lit = 0;
5009   
5010   resolveIfx (&rIfx, ifx);
5011
5012   /* handle for special cases */
5013   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5014       return;
5015
5016   /**********************************************************************
5017    * handle bits - bit compares are promoted to int compares seemingly! *
5018    **********************************************************************/
5019 #if 0
5020   // THIS IS COMPLETELY UNTESTED!
5021   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5022     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5023     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5024     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5025
5026     emitSETC;
5027     // 1 < {0,1} is false --> clear C by skipping the next instruction
5028     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5029     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5030     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5031     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5032     emitCLRC; // only skipped for left=0 && right=1
5033
5034     goto correct_result_in_carry;
5035   } // if
5036 #endif
5037
5038   /*************************************************
5039    * make sure that left is register (or the like) *
5040    *************************************************/
5041   if (!isAOP_REGlike(left)) {
5042     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5043     assert (isAOP_LIT(left));
5044     assert (isAOP_REGlike(right));
5045     // swap left and right
5046     // left < right <==> right > left <==> (right >= left + 1)
5047     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5048
5049     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5050       // MAXVALUE < right? always false
5051       if (performedLt) emitCLRC; else emitSETC;
5052       goto correct_result_in_carry;
5053     } // if
5054
5055     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5056     // that's why we handled it above.
5057     lit++;
5058
5059     dummy = left;
5060     left = right;
5061     right = dummy;
5062
5063     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5064   } else if (isAOP_LIT(right)) {
5065     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5066   } // if
5067
5068   assert (isAOP_REGlike(left)); // left must be register or the like
5069   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5070
5071   /*************************************************
5072    * special cases go here                         *
5073    *************************************************/
5074
5075   if (isAOP_LIT(right)) {
5076     if (!sign) {
5077       // unsigned comparison to a literal
5078       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5079       if (lit == 0) {
5080         // unsigned left < 0? always false
5081         if (performedLt) emitCLRC; else emitSETC;
5082         goto correct_result_in_carry;
5083       }
5084     } else {
5085       // signed comparison to a literal
5086       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5087       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5088         // signed left < 0x80000000? always false
5089         if (performedLt) emitCLRC; else emitSETC;
5090         goto correct_result_in_carry;
5091       } else if (lit == 0) {
5092         // compare left < 0; set CARRY if SIGNBIT(left) is set
5093         if (performedLt) emitSETC; else emitCLRC;
5094         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5095         if (performedLt) emitCLRC; else emitSETC;
5096         goto correct_result_in_carry;
5097       }
5098     } // if (!sign)
5099   } // right is literal
5100
5101   /*************************************************
5102    * perform a general case comparison             *
5103    * make sure we get CARRY==1 <==> left >= right  *
5104    *************************************************/
5105   // compare most significant bytes
5106   //DEBUGpc ("comparing bytes at offset %d", size);
5107   if (!sign) {
5108     // unsigned comparison
5109     mov2w_regOrLit (AOP(right), lit, size);
5110     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5111   } else {
5112     // signed comparison
5113     // (add 2^n to both operands then perform an unsigned comparison)
5114     if (isAOP_LIT(right)) {
5115       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5116       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5117
5118       if (litbyte == 0x80) {
5119         // left >= 0x80 -- always true, but more bytes to come
5120         pic16_mov2w (AOP(left), size);
5121         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5122         emitSETC;
5123       } else {
5124         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5125         pic16_mov2w (AOP(left), size);
5126         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5128       } // if
5129     } else {
5130       /* using PRODL as a temporary register here */
5131       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133       pic16_mov2w (AOP(left), size);
5134       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135       pic16_emitpcode (POC_MOVWF, pctemp);
5136       pic16_mov2w (AOP(right), size);
5137       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138       pic16_emitpcode (POC_SUBFW, pctemp);
5139       //pic16_popReleaseTempReg(pctemp, 1);
5140     }
5141   } // if (!sign)
5142
5143   // compare remaining bytes (treat as unsigned case from above)
5144   templbl = newiTempLabel ( NULL );
5145   offs = size;
5146   while (offs--) {
5147     //DEBUGpc ("comparing bytes at offset %d", offs);
5148     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149     mov2w_regOrLit (AOP(right), lit, offs);
5150     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5151   } // while (offs)
5152   pic16_emitpLabel (templbl->key);
5153   goto result_in_carry;
5154
5155 result_in_carry:
5156   
5157   /****************************************************
5158    * now CARRY contains the result of the comparison: *
5159    * SUBWF sets CARRY iff                             *
5160    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5161    * (F=left, W=right)                                *
5162    ****************************************************/
5163
5164   if (performedLt) {
5165     if (result && AOP_TYPE(result) != AOP_CRY) {
5166       // value will be stored
5167       emitTOGC;
5168     } else {
5169       // value wil only be used in the following genSkipc()
5170       rIfx.condition ^= 1;
5171     }
5172   } // if
5173
5174 correct_result_in_carry:
5175
5176   // assign result to variable (if neccessary)
5177   if (result && AOP_TYPE(result) != AOP_CRY) {
5178     //DEBUGpc ("assign result");
5179     size = AOP_SIZE(result);
5180     while (size--) {
5181       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5182     } // while
5183     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5184   } // if (result)
5185
5186   // perform conditional jump
5187   if (ifx) {
5188     //DEBUGpc ("generate control flow");
5189     genSkipc (&rIfx);
5190     ifx->generated = 1;
5191   } // if
5192 }
5193
5194 #elif 1         /* } */
5195                 /* { */
5196       /* original code */
5197 static void genCmp (operand *left,operand *right,
5198                     operand *result, iCode *ifx, int sign)
5199 {
5200   int size; //, offset = 0 ;
5201   unsigned long lit = 0L,i = 0;
5202   resolvedIfx rFalseIfx;
5203   //  resolvedIfx rTrueIfx;
5204   symbol *truelbl;
5205   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206 /*
5207   if(ifx) {
5208     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5210   }
5211 */
5212
5213   FENTRY;
5214   
5215   resolveIfx(&rFalseIfx,ifx);
5216   truelbl  = newiTempLabel(NULL);
5217   size = max(AOP_SIZE(left),AOP_SIZE(right));
5218
5219   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5220
5221 #define _swapp
5222
5223   /* if literal is on the right then swap with left */
5224   if ((AOP_TYPE(right) == AOP_LIT)) {
5225     operand *tmp = right ;
5226     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5228 #ifdef _swapp
5229
5230     lit = (lit - 1) & mask;
5231     right = left;
5232     left = tmp;
5233     rFalseIfx.condition ^= 1;
5234 #endif
5235
5236   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5238   }
5239
5240
5241   //if(IC_TRUE(ifx) == NULL)
5242   /* if left & right are bit variables */
5243   if (AOP_TYPE(left) == AOP_CRY &&
5244       AOP_TYPE(right) == AOP_CRY ) {
5245     assert (0 && "bit variables used in genCmp");
5246     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5248   } else {
5249     /* subtract right from left if at the
5250        end the carry flag is set then we know that
5251        left is greater than right */
5252
5253     symbol *lbl  = newiTempLabel(NULL);
5254
5255 #if 0
5256         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5258 #endif
5259
5260 #ifndef _swapp
5261     if(AOP_TYPE(right) == AOP_LIT) {
5262
5263       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5264
5265       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5266
5267       /* special cases */
5268
5269       if(lit == 0) {
5270
5271         if(sign != 0) 
5272           genSkipCond(&rFalseIfx,left,size-1,7);
5273         else 
5274           /* no need to compare to 0...*/
5275           /* NOTE: this is a de-generate compare that most certainly 
5276            *       creates some dead code. */
5277           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5278
5279         if(ifx) ifx->generated = 1;
5280         return;
5281
5282       }
5283       size--;
5284
5285       if(size == 0) {
5286         //i = (lit >> (size*8)) & 0xff;
5287         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5288         
5289         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290
5291         i = ((0-lit) & 0xff);
5292         if(sign) {
5293           if( i == 0x81) { 
5294             /* lit is 0x7f, all signed chars are less than
5295              * this except for 0x7f itself */
5296             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297             genSkipz2(&rFalseIfx,0);
5298           } else {
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301             genSkipc(&rFalseIfx);
5302           }
5303
5304         } else {
5305           if(lit == 1) {
5306             genSkipz2(&rFalseIfx,1);
5307           } else {
5308             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309             genSkipc(&rFalseIfx);
5310           }
5311         }
5312
5313         if(ifx) ifx->generated = 1;
5314         return;
5315       }
5316
5317       /* chars are out of the way. now do ints and longs */
5318
5319
5320       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5321         
5322       /* special cases */
5323
5324       if(sign) {
5325
5326         if(lit == 0) {
5327           genSkipCond(&rFalseIfx,left,size,7);
5328           if(ifx) ifx->generated = 1;
5329           return;
5330         }
5331
5332         if(lit <0x100) {
5333           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334
5335           //rFalseIfx.condition ^= 1;
5336           //genSkipCond(&rFalseIfx,left,size,7);
5337           //rFalseIfx.condition ^= 1;
5338
5339           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340           if(rFalseIfx.condition)
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5342           else
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344
5345           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5348
5349           while(size > 1)
5350             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5351
5352           if(rFalseIfx.condition) {
5353             emitSKPZ;
5354             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5355
5356           } else {
5357             emitSKPNZ;
5358           }
5359
5360           genSkipc(&rFalseIfx);
5361           pic16_emitpLabel(truelbl->key);
5362           if(ifx) ifx->generated = 1;
5363           return;
5364
5365         }
5366
5367         if(size == 1) {
5368
5369           if( (lit & 0xff) == 0) {
5370             /* lower byte is zero */
5371             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372             i = ((lit >> 8) & 0xff) ^0x80;
5373             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376             genSkipc(&rFalseIfx);
5377
5378
5379             if(ifx) ifx->generated = 1;
5380             return;
5381
5382           }
5383         } else {
5384           /* Special cases for signed longs */
5385           if( (lit & 0xffffff) == 0) {
5386             /* lower byte is zero */
5387             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388             i = ((lit >> 8*3) & 0xff) ^0x80;
5389             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392             genSkipc(&rFalseIfx);
5393
5394
5395             if(ifx) ifx->generated = 1;
5396             return;
5397
5398           }
5399
5400         }
5401
5402
5403         if(lit & (0x80 << (size*8))) {
5404           /* lit is negative */
5405           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5406
5407           //genSkipCond(&rFalseIfx,left,size,7);
5408
5409           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5410
5411           if(rFalseIfx.condition)
5412             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5413           else
5414             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5415
5416
5417         } else {
5418           /* lit is positive */
5419           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421           if(rFalseIfx.condition)
5422             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5423           else
5424             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5425
5426         }
5427
5428         /*
5429           This works, but is only good for ints.
5430           It also requires a "known zero" register.
5431           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5434           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436           genSkipc(&rFalseIfx);
5437
5438           pic16_emitpLabel(truelbl->key);
5439           if(ifx) ifx->generated = 1;
5440           return;
5441         **/
5442           
5443         /* There are no more special cases, so perform a general compare */
5444   
5445         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447
5448         while(size--) {
5449
5450           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5451           emitSKPNZ;
5452           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5453         }
5454         //rFalseIfx.condition ^= 1;
5455         genSkipc(&rFalseIfx);
5456
5457         pic16_emitpLabel(truelbl->key);
5458
5459         if(ifx) ifx->generated = 1;
5460         return;
5461
5462
5463       }
5464
5465
5466       /* sign is out of the way. So now do an unsigned compare */
5467       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5468
5469
5470       /* General case - compare to an unsigned literal on the right.*/
5471
5472       i = (lit >> (size*8)) & 0xff;
5473       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5475       while(size--) {
5476         i = (lit >> (size*8)) & 0xff;
5477
5478         if(i) {
5479           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5480           emitSKPNZ;
5481           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5482         } else {
5483           /* this byte of the lit is zero, 
5484            *if it's not the last then OR in the variable */
5485           if(size)
5486             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487         }
5488       }
5489
5490
5491       pic16_emitpLabel(lbl->key);
5492 //      pic16_emitpLabel(truelbl->key);
5493       //if(emitFinalCheck)
5494       genSkipc(&rFalseIfx);
5495       if(sign)
5496         pic16_emitpLabel(truelbl->key);
5497
5498       if(ifx) ifx->generated = 1;
5499       return;
5500
5501
5502     }
5503 #endif  // _swapp
5504
5505     if(AOP_TYPE(left) == AOP_LIT) {
5506       //symbol *lbl = newiTempLabel(NULL);
5507
5508       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5509
5510
5511       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5512
5513       /* Special cases */
5514       if((lit == 0) && (sign == 0)){
5515
5516         size--;
5517         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5518         while(size) 
5519           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5520
5521         genSkipz2(&rFalseIfx,0);
5522         if(ifx) ifx->generated = 1;
5523         return;
5524       }
5525
5526       if(size==1) {
5527         /* Special cases */
5528         lit &= 0xff;
5529         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530           /* degenerate compare can never be true */
5531           if(rFalseIfx.condition == 0)
5532             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5533
5534           if(ifx) ifx->generated = 1;
5535           return;
5536         }
5537
5538         if(sign) {
5539           /* signed comparisons to a literal byte */
5540
5541           int lp1 = (lit+1) & 0xff;
5542
5543           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5544           switch (lp1) {
5545           case 0:
5546             rFalseIfx.condition ^= 1;
5547             genSkipCond(&rFalseIfx,right,0,7);
5548             break;
5549           case 0x7f:
5550             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552             genSkipz2(&rFalseIfx,1);
5553             break;
5554           default:
5555             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558             rFalseIfx.condition ^= 1;
5559             genSkipc(&rFalseIfx);
5560             break;
5561           }
5562         } else {
5563           /* unsigned comparisons to a literal byte */
5564
5565           switch(lit & 0xff ) {
5566           case 0:
5567             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568             genSkipz2(&rFalseIfx,0);
5569             break;
5570           case 0x7f:
5571             rFalseIfx.condition ^= 1;
5572             genSkipCond(&rFalseIfx,right,0,7);
5573             break;
5574
5575           default:
5576             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5579             rFalseIfx.condition ^= 1;
5580             if (AOP_TYPE(result) == AOP_CRY)
5581               genSkipc(&rFalseIfx);
5582             else {
5583               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5585             }         
5586             break;
5587           }
5588         }
5589
5590         if(ifx) ifx->generated = 1;
5591         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5592                 goto check_carry;
5593         return;
5594
5595       } else {
5596
5597         /* Size is greater than 1 */
5598
5599         if(sign) {
5600           int lp1 = lit+1;
5601
5602           size--;
5603
5604           if(lp1 == 0) {
5605             /* this means lit = 0xffffffff, or -1 */
5606
5607
5608             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609             rFalseIfx.condition ^= 1;
5610             genSkipCond(&rFalseIfx,right,size,7);
5611             if(ifx) ifx->generated = 1;
5612
5613             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5614               goto check_carry;
5615
5616             return;
5617           }
5618
5619           if(lit == 0) {
5620             int s = size;
5621
5622             if(rFalseIfx.condition) {
5623               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5625             }
5626
5627             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5628             while(size--)
5629               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5630
5631
5632             emitSKPZ;
5633             if(rFalseIfx.condition) {
5634               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5635               pic16_emitpLabel(truelbl->key);
5636             }else {
5637               rFalseIfx.condition ^= 1;
5638               genSkipCond(&rFalseIfx,right,s,7);
5639             }
5640
5641             if(ifx) ifx->generated = 1;
5642
5643             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5644               goto check_carry;
5645
5646             return;
5647           }
5648
5649           if((size == 1) &&  (0 == (lp1&0xff))) {
5650             /* lower byte of signed word is zero */
5651             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5652             i = ((lp1 >> 8) & 0xff) ^0x80;
5653             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5656
5657             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5658               emitTOGC;
5659               if(ifx) ifx->generated = 1;
5660               goto check_carry;
5661             } else {
5662               rFalseIfx.condition ^= 1;
5663               genSkipc(&rFalseIfx);
5664               if(ifx) ifx->generated = 1;
5665             }
5666
5667             return;
5668           }
5669
5670           if(lit & (0x80 << (size*8))) {
5671             /* Lit is less than zero */
5672             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5673             //rFalseIfx.condition ^= 1;
5674             //genSkipCond(&rFalseIfx,left,size,7);
5675             //rFalseIfx.condition ^= 1;
5676             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5678
5679             if(rFalseIfx.condition)
5680               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5681             else
5682               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5683
5684
5685           } else {
5686             /* Lit is greater than or equal to zero */
5687             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5688             //rFalseIfx.condition ^= 1;
5689             //genSkipCond(&rFalseIfx,right,size,7);
5690             //rFalseIfx.condition ^= 1;
5691
5692             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5694
5695             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696             if(rFalseIfx.condition)
5697               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5698             else
5699               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5700
5701           }
5702
5703           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705
5706           while(size--) {
5707
5708             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5709             emitSKPNZ;
5710             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5711           }
5712           rFalseIfx.condition ^= 1;
5713           //rFalseIfx.condition = 1;
5714           genSkipc(&rFalseIfx);
5715
5716           pic16_emitpLabel(truelbl->key);
5717
5718           if(ifx) ifx->generated = 1;
5719
5720
5721           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5722             goto check_carry;
5723
5724           return;
5725           // end of if (sign)
5726         } else {
5727
5728           /* compare word or long to an unsigned literal on the right.*/
5729
5730
5731           size--;
5732           if(lit < 0xff) {
5733             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5734             switch (lit) {
5735             case 0:
5736               break; /* handled above */
5737 /*
5738             case 0xff:
5739               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5740               while(size--)
5741                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742               genSkipz2(&rFalseIfx,0);
5743               break;
5744 */
5745             default:
5746               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5747               while(--size)
5748                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5749
5750               emitSKPZ;
5751               if(rFalseIfx.condition)
5752                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5753               else
5754                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5755
5756
5757               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5759
5760               rFalseIfx.condition ^= 1;
5761               genSkipc(&rFalseIfx);
5762             }
5763
5764             pic16_emitpLabel(truelbl->key);
5765
5766             if(ifx) ifx->generated = 1;
5767
5768             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769               goto check_carry;
5770
5771             return;
5772           }
5773
5774
5775           lit++;
5776           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777           i = (lit >> (size*8)) & 0xff;
5778
5779           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5781
5782           while(size--) {
5783             i = (lit >> (size*8)) & 0xff;
5784
5785             if(i) {
5786               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5787               emitSKPNZ;
5788               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5789             } else {
5790               /* this byte of the lit is zero, 
5791                * if it's not the last then OR in the variable */
5792               if(size)
5793                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794             }
5795           }
5796
5797
5798           pic16_emitpLabel(lbl->key);
5799
5800           rFalseIfx.condition ^= 1;
5801
5802           genSkipc(&rFalseIfx);
5803         }
5804
5805         if(sign)
5806           pic16_emitpLabel(truelbl->key);
5807         if(ifx) ifx->generated = 1;
5808
5809             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5810               goto check_carry;
5811
5812         return;
5813       }
5814     }
5815     /* Compare two variables */
5816
5817     DEBUGpic16_emitcode(";sign","%d",sign);
5818
5819     size--;
5820     if(sign) {
5821       /* Sigh. thus sucks... */
5822       if(size) {
5823         pCodeOp *pctemp;
5824         
5825         pctemp = pic16_popGetTempReg(1);
5826         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832         pic16_popReleaseTempReg(pctemp, 1);
5833       } else {
5834         /* Signed char comparison */
5835         /* Special thanks to Nikolai Golovchenko for this snippet */
5836         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5839         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5842
5843         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5844         genSkipc(&rFalseIfx);
5845           
5846         if(ifx) ifx->generated = 1;
5847
5848             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5849               goto check_carry;
5850
5851         return;
5852       }
5853
5854     } else {
5855
5856       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5858     }
5859
5860
5861     /* The rest of the bytes of a multi-byte compare */
5862     while (size) {
5863
5864       emitSKPZ;
5865       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5866       size--;
5867
5868       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870
5871
5872     }
5873
5874     pic16_emitpLabel(lbl->key);
5875
5876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5877     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5878         (AOP_TYPE(result) == AOP_REG)) {
5879       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5881     } else {
5882       genSkipc(&rFalseIfx);
5883     }         
5884     //genSkipc(&rFalseIfx);
5885     if(ifx) ifx->generated = 1;
5886
5887
5888             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889               goto check_carry;
5890
5891     return;
5892
5893   }
5894
5895 check_carry:
5896   if ((AOP_TYPE(result) != AOP_CRY) 
5897         && AOP_SIZE(result)) {
5898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899
5900     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5901
5902     pic16_outBitC(result);
5903   } else {
5904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5905     /* if the result is used in the next
5906        ifx conditional branch then generate
5907        code a little differently */
5908     if (ifx )
5909       genIfxJump (ifx,"c");
5910     else
5911       pic16_outBitC(result);
5912     /* leave the result in acc */
5913   }
5914
5915 }
5916
5917 #elif 0 /* VR version of genCmp() */    /* } else { */
5918
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921         operand *result, int offset, int invert_op)
5922 {
5923   /* add code here */
5924   
5925   /* check condition, > or < ?? */
5926   if(rIfx->condition != 0)invert_op ^= 1;
5927   
5928   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5929
5930   if(!ifx)invert_op ^= 1;
5931
5932   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5934   
5935   /* do selection */
5936   if(!invert_op)return POC_CPFSGT;
5937   else return POC_CPFSLT;
5938 }
5939
5940 static int compareAopfirstpass=1;
5941
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943             operand *oper, int offset, operand *result,
5944             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5945             symbol *tlbl)
5946 {
5947   int op;
5948   symbol *truelbl;
5949
5950   /* invert if there is a result to be loaded, in order to fit,
5951    * SETC/CLRC sequence */
5952   if(AOP_SIZE(result))invert_op ^= 1;
5953
5954 //  if(sign && !offset)invert_op ^= 1;
5955   
5956 //  if(sign)invert_op ^= 1;
5957   
5958   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5959
5960   if(AOP_SIZE(result) && compareAopfirstpass) {
5961     if(!ifx) {
5962       if(pcop2)
5963         pic16_emitpcode(POC_SETF, pcop2);
5964       else
5965         emitSETC;
5966     } else {
5967       if(pcop2)
5968         pic16_emitpcode(POC_CLRF, pcop2);
5969       else
5970         emitCLRC;
5971     }
5972   }
5973
5974   compareAopfirstpass = 0;
5975
5976       /* there is a bug when comparing operands with size > 1,
5977        * because higher bytes can be equal and test should be performed
5978        * to the next lower byte, current algorithm, considers operands
5979        * inequal in these cases! -- VR 20041107 */
5980
5981     
5982   if(pcop)
5983     pic16_emitpcode(op, pcop);
5984   else
5985     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5986
5987
5988   if((!sign || !offset) && AOP_SIZE(result)) {
5989     if(!ifx) {
5990       if(pcop2)
5991         pic16_emitpcode(POC_CLRF, pcop2);
5992         else
5993         emitCLRC;
5994     } else {
5995       if(pcop2)
5996         pic16_emitpcode(POC_SETF, pcop2);
5997       else
5998         emitSETC;
5999     }
6000     
6001     /* don't emit final branch (offset == 0) */
6002     if(offset) {
6003
6004       if(pcop2)
6005         pic16_emitpcode(POC_RRCF, pcop2);
6006
6007       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6008     }
6009   } else {
6010     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6013
6014       truelbl = newiTempLabel( NULL );
6015       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6018       else
6019         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020       pic16_emitpLabel(truelbl->key);
6021     } else {
6022       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023     }
6024   }
6025 }
6026
6027 static void genCmp (operand *left, operand *right,
6028                     operand *result, iCode *ifx, int sign)
6029 {
6030   int size, cmpop=1;
6031   long lit = 0L;
6032   resolvedIfx rFalseIfx;
6033   symbol *falselbl, *tlbl;
6034
6035     FENTRY;
6036     
6037     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6038
6039     resolveIfx(&rFalseIfx, ifx);
6040     size = max(AOP_SIZE(left), AOP_SIZE(right));
6041     
6042     /* if left & right are bit variables */
6043     if(AOP_TYPE(left) == AOP_CRY
6044       && AOP_TYPE(right) == AOP_CRY ) {
6045
6046         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6048         
6049         werror(W_POSSBUG2, __FILE__, __LINE__);
6050         exit(-1);
6051     }
6052     
6053     /* if literal is on the right then swap with left */
6054     if((AOP_TYPE(right) == AOP_LIT)) {
6055       operand *tmp = right ;
6056 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6057
6058         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6059
6060 //      lit = (lit - 1) & mask;
6061         right = left;
6062         left = tmp;
6063         rFalseIfx.condition ^= 1;               /* reverse compare */
6064     } else
6065     if ((AOP_TYPE(left) == AOP_LIT)) {
6066       /* float compares are handled by support functions */
6067       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6068     }
6069
6070     /* actual comparing algorithm */
6071 //    size = AOP_SIZE( right );
6072
6073     falselbl = newiTempLabel( NULL );
6074     if(AOP_TYPE(left) == AOP_LIT) {
6075       /* compare to literal */
6076       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6077       
6078       if(sign) {
6079         pCodeOp *pct, *pct2;
6080         symbol *tlbl1;
6081
6082         /* signed compare */
6083         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6084
6085         /* using PRODL:PRODH as a temporary register here */
6086         pct = pic16_popCopyReg(&pic16_pc_prodl);
6087         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6088         tlbl = newiTempLabel( NULL );
6089         
6090         /* first compare signs:
6091          *  a. if both are positive, compare just like unsigned
6092          *  b. if both are negative, invert cmpop, compare just like unsigned
6093          *  c. if different signs, determine the result directly */
6094
6095         size--;
6096
6097 #if 1
6098         /* { */
6099         tlbl1 = newiTempLabel( NULL );
6100 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6101
6102         if(lit > 0) {
6103
6104           /* literal is zero or positive:
6105            *  a. if carry is zero, too, continue compare,
6106            *  b. if carry is set, then continue depending on cmpop ^ condition:
6107            *    1. '<' return false (literal < variable),
6108            *    2. '>' return true (literal > variable) */
6109 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6110           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6111           
6112           
6113           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6115         } else 
6116         if(lit < 0) {
6117           
6118           /* literal is negative:
6119            *  a. if carry is set, too, continue compare,
6120            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6121            *    1. '<' return true (literal < variable),
6122            *    2. '>' return false (literal > variable) */
6123 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6124           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6125           
6126           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6128         }
6129 #if 1
6130         else {
6131           /* lit == 0 */
6132           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6133           
6134           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6135           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6136         }
6137 #endif
6138         
6139         
6140         pic16_emitpLabel( tlbl1->key );
6141 #endif  /* } */
6142
6143         compareAopfirstpass=1;
6144 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6145 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 //        pic16_emitpcode(POC_MOVWF, pct);
6147
6148 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6150 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6152
6153         /* generic case */        
6154           while( size-- ) {
6155 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6156 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6157 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6158 //            pic16_emitpcode(POC_MOVWF, pct);
6159
6160 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6161             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6162             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6163 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6165           }
6166         
6167         if(ifx)ifx->generated = 1;
6168
6169         if(AOP_SIZE(result)) {
6170           pic16_emitpLabel(tlbl->key);
6171           pic16_emitpLabel(falselbl->key);
6172           pic16_outBitOp( result, pct2 );
6173         } else {
6174           pic16_emitpLabel(tlbl->key);
6175         }
6176       } else {
6177
6178         /* unsigned compare */      
6179         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6180     
6181         compareAopfirstpass=1;
6182         while(size--) {
6183           
6184           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6185           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6186
6187         }
6188         if(ifx)ifx->generated = 1;
6189
6190         if(AOP_SIZE(result)) {
6191           pic16_emitpLabel(falselbl->key);
6192           pic16_outBitC( result );
6193         }
6194
6195       }
6196     } else {
6197       /* compare registers */
6198       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6199
6200
6201       if(sign) {
6202         pCodeOp *pct, *pct2;
6203         
6204         /* signed compare */
6205         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6206
6207         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6208         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6209         tlbl = newiTempLabel( NULL );
6210         
6211         compareAopfirstpass=1;
6212
6213         size--;
6214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6215 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217         pic16_emitpcode(POC_MOVWF, pct);
6218
6219         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6220 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6221         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6222
6223         /* WREG already holds left + 0x80 */
6224         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6225         
6226         while( size-- ) {
6227           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6228 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230           pic16_emitpcode(POC_MOVWF, pct);
6231                 
6232           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6233 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6234           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6235
6236           /* WREG already holds left + 0x80 */
6237           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6238 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6239         }
6240         
6241         if(ifx)ifx->generated = 1;
6242
6243         if(AOP_SIZE(result)) {
6244           pic16_emitpLabel(tlbl->key);
6245           pic16_emitpLabel(falselbl->key);
6246           pic16_outBitOp( result, pct2 );
6247         } else {
6248           pic16_emitpLabel(tlbl->key);
6249         }
6250
6251       } else {
6252         /* unsigned compare */      
6253         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6254
6255         compareAopfirstpass=1;
6256         while(size--) {
6257           
6258           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6259           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6260
6261         }
6262
6263         if(ifx)ifx->generated = 1;
6264         if(AOP_SIZE(result)) {
6265
6266           pic16_emitpLabel(falselbl->key);
6267           pic16_outBitC( result );
6268         }
6269
6270       }
6271     }
6272 }
6273
6274 #endif  /* } */
6275
6276
6277
6278 /*-----------------------------------------------------------------*/
6279 /* genCmpGt :- greater than comparison                             */
6280 /*-----------------------------------------------------------------*/
6281 static void genCmpGt (iCode *ic, iCode *ifx)
6282 {
6283   operand *left, *right, *result;
6284   sym_link *letype , *retype;
6285   int sign ;
6286
6287     FENTRY;
6288     
6289     left = IC_LEFT(ic);
6290     right= IC_RIGHT(ic);
6291     result = IC_RESULT(ic);
6292
6293     letype = getSpec(operandType(left));
6294     retype =getSpec(operandType(right));
6295     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6296     /* assign the amsops */
6297     pic16_aopOp (left,ic,FALSE);
6298     pic16_aopOp (right,ic,FALSE);
6299     pic16_aopOp (result,ic,TRUE);
6300
6301     genCmp(right, left, result, ifx, sign);
6302
6303     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6305     pic16_freeAsmop(result,NULL,ic,TRUE); 
6306 }
6307
6308 /*-----------------------------------------------------------------*/
6309 /* genCmpLt - less than comparisons                                */
6310 /*-----------------------------------------------------------------*/
6311 static void genCmpLt (iCode *ic, iCode *ifx)
6312 {
6313   operand *left, *right, *result;
6314   sym_link *letype , *retype;
6315   int sign ;
6316
6317     FENTRY;
6318
6319     left = IC_LEFT(ic);
6320     right= IC_RIGHT(ic);
6321     result = IC_RESULT(ic);
6322
6323     letype = getSpec(operandType(left));
6324     retype =getSpec(operandType(right));
6325     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6326
6327     /* assign the amsops */
6328     pic16_aopOp (left,ic,FALSE);
6329     pic16_aopOp (right,ic,FALSE);
6330     pic16_aopOp (result,ic,TRUE);
6331
6332     genCmp(left, right, result, ifx, sign);
6333
6334     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6336     pic16_freeAsmop(result,NULL,ic,TRUE); 
6337 }
6338
6339 #if 0
6340 // not needed ATM
6341 // FIXME reenable literal optimisation when the pic16 port is stable
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genc16bit2lit - compare a 16 bit value to a literal             */
6345 /*-----------------------------------------------------------------*/
6346 static void genc16bit2lit(operand *op, int lit, int offset)
6347 {
6348   int i;
6349
6350   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6351   if( (lit&0xff) == 0) 
6352     i=1;
6353   else
6354     i=0;
6355
6356   switch( BYTEofLONG(lit,i)) { 
6357   case 0:
6358     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359     break;
6360   case 1:
6361     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6362     break;
6363   case 0xff:
6364     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6365     break;
6366   default:
6367     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6368     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6369   }
6370
6371   i ^= 1;
6372
6373   switch( BYTEofLONG(lit,i)) { 
6374   case 0:
6375     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6376     break;
6377   case 1:
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6380     break;
6381   case 0xff:
6382     emitSKPNZ;
6383     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6384     break;
6385   default:
6386     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6387     emitSKPNZ;
6388     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6389
6390   }
6391
6392 }
6393 #endif
6394
6395 #if 0
6396 // not needed ATM
6397 /*-----------------------------------------------------------------*/
6398 /* gencjneshort - compare and jump if not equal                    */
6399 /*-----------------------------------------------------------------*/
6400 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6401 {
6402   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6403   int offset = 0;
6404   int res_offset = 0;  /* the result may be a different size then left or right */
6405   int res_size = AOP_SIZE(result);
6406   resolvedIfx rIfx;
6407   symbol *lbl, *lbl_done;
6408
6409   unsigned long lit = 0L;
6410   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6411
6412   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6413   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6414   if(result)
6415     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6416   resolveIfx(&rIfx,ifx);
6417   lbl =  newiTempLabel(NULL);
6418   lbl_done =  newiTempLabel(NULL);
6419
6420
6421   /* if the left side is a literal or 
6422      if the right is in a pointer register and left 
6423      is not */
6424   if ((AOP_TYPE(left) == AOP_LIT) || 
6425       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6426     operand *t = right;
6427     right = left;
6428     left = t;
6429   }
6430   if(AOP_TYPE(right) == AOP_LIT)
6431     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6432
6433   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6434     preserve_result = 1;
6435
6436   if(result && !preserve_result)
6437     {
6438       int i;
6439       for(i = 0; i < AOP_SIZE(result); i++)
6440         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6441     }
6442
6443
6444   /* if the right side is a literal then anything goes */
6445   if (AOP_TYPE(right) == AOP_LIT &&
6446       AOP_TYPE(left) != AOP_DIR ) {
6447     switch(size) {
6448     case 2:
6449       genc16bit2lit(left, lit, 0);
6450       emitSKPZ;
6451       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6452       break;
6453     default:
6454       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6455       while (size--) {
6456         if(lit & 0xff) {
6457           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6458           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6459         } else {
6460           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6461         }
6462
6463         emitSKPZ;
6464         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6465         offset++;
6466         if(res_offset < res_size-1)
6467           res_offset++;
6468         lit >>= 8;
6469       }
6470       break;
6471     }
6472   }
6473
6474   /* if the right side is in a register or in direct space or
6475      if the left is a pointer register & right is not */    
6476   else if (AOP_TYPE(right) == AOP_REG ||
6477            AOP_TYPE(right) == AOP_DIR || 
6478            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6479            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6480     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6481     int lbl_key = lbl->key;
6482
6483     if(result) {
6484       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6485       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6486     }else {
6487       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6488       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6489               __FUNCTION__,__LINE__);
6490       return;
6491     }
6492    
6493 /*     switch(size) { */
6494 /*     case 2: */
6495 /*       genc16bit2lit(left, lit, 0); */
6496 /*       emitSKPNZ; */
6497 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6498 /*       break; */
6499 /*     default: */
6500     while (size--) {
6501       int emit_skip=1;
6502       if((AOP_TYPE(left) == AOP_DIR) && 
6503          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6504
6505         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6507
6508       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6509             
6510         switch (lit & 0xff) {
6511         case 0:
6512           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513           break;
6514         case 1:
6515           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6516           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6518           emit_skip=0;
6519           break;
6520         case 0xff:
6521           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6523           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6524           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6525           emit_skip=0;
6526           break;
6527         default:
6528           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6529           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6530         }
6531         lit >>= 8;
6532
6533       } else {
6534         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6535       }
6536       if(emit_skip) {
6537         if(AOP_TYPE(result) == AOP_CRY) {
6538           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6539           if(rIfx.condition)
6540             emitSKPNZ;
6541           else
6542             emitSKPZ;
6543           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6544         } else {
6545           /* fix me. probably need to check result size too */
6546           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6547           if(rIfx.condition)
6548             emitSKPZ;
6549           else
6550             emitSKPNZ;
6551           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6552           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6553         }
6554         if(ifx)
6555           ifx->generated=1;
6556       }
6557       emit_skip++;
6558       offset++;
6559       if(res_offset < res_size-1)
6560         res_offset++;
6561     }
6562 /*       break; */
6563 /*     } */
6564   } else if(AOP_TYPE(right) == AOP_REG &&
6565             AOP_TYPE(left) != AOP_DIR){
6566
6567     while(size--) {
6568       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6569       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6570       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6571       if(rIfx.condition)
6572         emitSKPNZ;
6573       else
6574         emitSKPZ;
6575       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6576       offset++;
6577       if(res_offset < res_size-1)
6578         res_offset++;
6579     }
6580       
6581   }else{
6582     /* right is a pointer reg need both a & b */
6583     while(size--) {
6584       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6585       if(strcmp(l,"b"))
6586         pic16_emitcode("mov","b,%s",l);
6587       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6589       offset++;
6590     }
6591   }
6592
6593   if(result && preserve_result)
6594     {
6595       int i;
6596       for(i = 0; i < AOP_SIZE(result); i++)
6597         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6598     }
6599
6600   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6601
6602   if(result && preserve_result)
6603     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6604
6605   if(!rIfx.condition)
6606     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6607
6608   pic16_emitpLabel(lbl->key);
6609
6610   if(result && preserve_result)
6611     {
6612       int i;
6613       for(i = 0; i < AOP_SIZE(result); i++)
6614         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6615
6616       pic16_emitpLabel(lbl_done->key);
6617    }
6618
6619   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6620
6621   if(ifx)
6622     ifx->generated = 1;
6623 }
6624 #endif
6625
6626 #if 0
6627 /*-----------------------------------------------------------------*/
6628 /* gencjne - compare and jump if not equal                         */
6629 /*-----------------------------------------------------------------*/
6630 static void gencjne(operand *left, operand *right, iCode *ifx)
6631 {
6632     symbol *tlbl  = newiTempLabel(NULL);
6633
6634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6635     gencjneshort(left, right, lbl);
6636
6637     pic16_emitcode("mov","a,%s",one);
6638     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6639     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6640     pic16_emitcode("clr","a");
6641     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6642
6643     pic16_emitpLabel(lbl->key);
6644     pic16_emitpLabel(tlbl->key);
6645
6646 }
6647 #endif
6648
6649
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitOp - check if operand has to be treated as literal        */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitOp(operand *op)
6654 {
6655   return ((AOP_TYPE(op) == AOP_LIT)
6656       || ( (AOP_TYPE(op) == AOP_PCODE)
6657           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6658               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6659 }
6660
6661 /*-----------------------------------------------------------------*/
6662 /* is_LitAOp - check if operand has to be treated as literal        */
6663 /*-----------------------------------------------------------------*/
6664 static bool is_LitAOp(asmop *aop)
6665 {
6666   return ((aop->type == AOP_LIT)
6667       || ( (aop->type == AOP_PCODE)
6668           && ( (aop->aopu.pcop->type == PO_LITERAL)
6669               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6670 }
6671
6672
6673
6674 /*-----------------------------------------------------------------*/
6675 /* genCmpEq - generates code for equal to                          */
6676 /*-----------------------------------------------------------------*/
6677 static void genCmpEq (iCode *ic, iCode *ifx)
6678 {
6679   operand *left, *right, *result;
6680   symbol *falselbl = newiTempLabel(NULL);
6681   symbol *donelbl = newiTempLabel(NULL);
6682
6683   int preserve_result = 0;
6684   int generate_result = 0;
6685   int i=0;
6686   unsigned long lit = -1;
6687
6688   FENTRY;
6689   
6690   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6691   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6692   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6693  
6694   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6695
6696   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6697     {
6698       werror(W_POSSBUG2, __FILE__, __LINE__);
6699       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6700       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6701       goto release;
6702     }
6703
6704   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6705     {
6706       operand *tmp = right ;
6707       right = left;
6708       left = tmp;
6709     }
6710
6711   if (AOP_TYPE(right) == AOP_LIT) {
6712     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6713   }
6714
6715   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6716     preserve_result = 1;
6717
6718   if(result && AOP_SIZE(result))
6719     generate_result = 1;
6720
6721   if(generate_result && !preserve_result)
6722     {
6723       for(i = 0; i < AOP_SIZE(result); i++)
6724         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6725     }
6726
6727   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6728   for(i=0; i < AOP_SIZE(left); i++)
6729     {
6730       if(AOP_TYPE(left) != AOP_ACC)
6731         {
6732           if(is_LitOp(left))
6733             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6734           else
6735             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6736         }
6737       if(is_LitOp(right)) {
6738         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6739           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6740         }
6741       } else
6742         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6743
6744       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6745     }
6746
6747   // result == true
6748
6749   if(generate_result && preserve_result)
6750     {
6751       for(i = 0; i < AOP_SIZE(result); i++)
6752         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6753     }
6754
6755   if(generate_result)
6756     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6757
6758   if(generate_result && preserve_result)
6759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6760
6761   if(ifx && IC_TRUE(ifx))
6762     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6763
6764   if(ifx && IC_FALSE(ifx))
6765     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6766
6767   pic16_emitpLabel(falselbl->key);
6768
6769   // result == false
6770
6771   if(ifx && IC_FALSE(ifx))
6772     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6773
6774   if(generate_result && preserve_result)
6775     {
6776       for(i = 0; i < AOP_SIZE(result); i++)
6777         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6778     }
6779
6780   pic16_emitpLabel(donelbl->key);
6781
6782   if(ifx)
6783     ifx->generated = 1;
6784
6785 release:
6786   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6787   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6788   pic16_freeAsmop(result,NULL,ic,TRUE);
6789
6790 }
6791
6792
6793 #if 0
6794 // old version kept for reference
6795
6796 /*-----------------------------------------------------------------*/
6797 /* genCmpEq - generates code for equal to                          */
6798 /*-----------------------------------------------------------------*/
6799 static void genCmpEq (iCode *ic, iCode *ifx)
6800 {
6801     operand *left, *right, *result;
6802     unsigned long lit = 0L;
6803     int size,offset=0;
6804     symbol *falselbl  = newiTempLabel(NULL);
6805
6806
6807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6808
6809     if(ifx)
6810       DEBUGpic16_emitcode ("; ifx is non-null","");
6811     else
6812       DEBUGpic16_emitcode ("; ifx is null","");
6813
6814     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6815     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6816     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6817
6818     size = max(AOP_SIZE(left),AOP_SIZE(right));
6819
6820     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6821
6822     /* if literal, literal on the right or 
6823     if the right is in a pointer register and left 
6824     is not */
6825     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6826         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6827       operand *tmp = right ;
6828       right = left;
6829       left = tmp;
6830     }
6831
6832
6833     if(ifx && !AOP_SIZE(result)){
6834         symbol *tlbl;
6835         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6836         /* if they are both bit variables */
6837         if (AOP_TYPE(left) == AOP_CRY &&
6838             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6839                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6840             if(AOP_TYPE(right) == AOP_LIT){
6841                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6842                 if(lit == 0L){
6843                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844                     pic16_emitcode("cpl","c");
6845                 } else if(lit == 1L) {
6846                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6847                 } else {
6848                     pic16_emitcode("clr","c");
6849                 }
6850                 /* AOP_TYPE(right) == AOP_CRY */
6851             } else {
6852                 symbol *lbl = newiTempLabel(NULL);
6853                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6854                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6855                 pic16_emitcode("cpl","c");
6856                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6857             }
6858             /* if true label then we jump if condition
6859             supplied is true */
6860             tlbl = newiTempLabel(NULL);
6861             if ( IC_TRUE(ifx) ) {
6862                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6863                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6864             } else {
6865                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6866                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6867             }
6868             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6869
6870                 {
6871                 /* left and right are both bit variables, result is carry */
6872                         resolvedIfx rIfx;
6873               
6874                         resolveIfx(&rIfx,ifx);
6875
6876                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6877                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6878                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6879                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6880                         genSkipz2(&rIfx,0);
6881                 }
6882         } else {
6883
6884                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6885
6886                         /* They're not both bit variables. Is the right a literal? */
6887                         if(AOP_TYPE(right) == AOP_LIT) {
6888                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6889             
6890                         switch(size) {
6891
6892                                 case 1:
6893                                         switch(lit & 0xff) {
6894                                                 case 1:
6895                                                                 if ( IC_TRUE(ifx) ) {
6896                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6897                                                                         emitSKPNZ;
6898                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6899                                                                 } else {
6900                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6901                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6902                                                                 }
6903                                                                 break;
6904                                                 case 0xff:
6905                                                                 if ( IC_TRUE(ifx) ) {
6906                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6907                                                                         emitSKPNZ;
6908                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6909                                                                 } else {
6910                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6911                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6912                                                                 }
6913                                                                 break;
6914                                                 default:
6915                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6916                                                                 if(lit)
6917                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6918                                                                 genSkip(ifx,'z');
6919                                         } // switch lit
6920
6921
6922                                         /* end of size == 1 */
6923                                         break;
6924               
6925                                 case 2:
6926                                         genc16bit2lit(left,lit,offset);
6927                                         genSkip(ifx,'z');
6928                                         break;
6929                                         /* end of size == 2 */
6930
6931                                 default:
6932                                         /* size is 4 */
6933                                         if(lit==0) {
6934                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6935                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6936                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6937                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6938                                                 genSkip(ifx,'z');
6939                                         } else {
6940                                                 /* search for patterns that can be optimized */
6941
6942                                                 genc16bit2lit(left,lit,0);
6943                                                 lit >>= 16;
6944                                                 if(lit) {
6945                                                                 if(IC_TRUE(ifx))
6946                                                                 emitSKPZ; // if hi word unequal
6947                                                                 else
6948                                                                 emitSKPNZ; // if hi word equal
6949                                                                 // fail early
6950                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6951                                                         genc16bit2lit(left,lit,2);
6952                                                         genSkip(ifx,'z');
6953                                                 } else {
6954                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6955                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6956                                                         genSkip(ifx,'z');
6957                                                 }
6958                                         }
6959                                                 pic16_emitpLabel(falselbl->key);
6960                                                 break;
6961
6962                         } // switch size
6963           
6964                         ifx->generated = 1;
6965                         goto release ;
6966             
6967
6968           } else if(AOP_TYPE(right) == AOP_CRY ) {
6969             /* we know the left is not a bit, but that the right is */
6970             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6971             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6972                       pic16_popGet(AOP(right),offset));
6973             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6974
6975             /* if the two are equal, then W will be 0 and the Z bit is set
6976              * we could test Z now, or go ahead and check the high order bytes if
6977              * the variable we're comparing is larger than a byte. */
6978
6979             while(--size)
6980               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6981
6982             if ( IC_TRUE(ifx) ) {
6983               emitSKPNZ;
6984               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6985               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6986             } else {
6987               emitSKPZ;
6988               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6989               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6990             }
6991
6992           } else {
6993             /* They're both variables that are larger than bits */
6994             int s = size;
6995
6996             tlbl = newiTempLabel(NULL);
6997
6998             while(size--) {
6999               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7000               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7001
7002               if ( IC_TRUE(ifx) ) {
7003                 if(size) {
7004                   emitSKPZ;
7005                 
7006                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7007
7008                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7009                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7010                 } else {
7011                   emitSKPNZ;
7012
7013                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7014
7015
7016                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7017                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7018                 }
7019               } else {
7020                 emitSKPZ;
7021
7022                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7023
7024                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7025                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7026               }
7027               offset++;
7028             }
7029             if(s>1 && IC_TRUE(ifx)) {
7030               pic16_emitpLabel(tlbl->key);
7031               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7032             }
7033           }
7034         }
7035         /* mark the icode as generated */
7036         ifx->generated = 1;
7037         goto release ;
7038     }
7039
7040     /* if they are both bit variables */
7041     if (AOP_TYPE(left) == AOP_CRY &&
7042         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7043         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7044         if(AOP_TYPE(right) == AOP_LIT){
7045             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7046             if(lit == 0L){
7047                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048                 pic16_emitcode("cpl","c");
7049             } else if(lit == 1L) {
7050                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7051             } else {
7052                 pic16_emitcode("clr","c");
7053             }
7054             /* AOP_TYPE(right) == AOP_CRY */
7055         } else {
7056             symbol *lbl = newiTempLabel(NULL);
7057             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7058             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7059             pic16_emitcode("cpl","c");
7060             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7061         }
7062         /* c = 1 if egal */
7063         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7064             pic16_outBitC(result);
7065             goto release ;
7066         }
7067         if (ifx) {
7068             genIfxJump (ifx,"c");
7069             goto release ;
7070         }
7071         /* if the result is used in an arithmetic operation
7072         then put the result in place */
7073         pic16_outBitC(result);
7074     } else {
7075       
7076       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7077       gencjne(left,right,result,ifx);
7078 /*
7079       if(ifx) 
7080         gencjne(left,right,newiTempLabel(NULL));
7081       else {
7082         if(IC_TRUE(ifx)->key)
7083           gencjne(left,right,IC_TRUE(ifx)->key);
7084         else
7085           gencjne(left,right,IC_FALSE(ifx)->key);
7086         ifx->generated = 1;
7087         goto release ;
7088       }
7089       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7090         pic16_aopPut(AOP(result),"a",0);
7091         goto release ;
7092       }
7093
7094       if (ifx) {
7095         genIfxJump (ifx,"a");
7096         goto release ;
7097       }
7098 */
7099       /* if the result is used in an arithmetic operation
7100          then put the result in place */
7101 /*
7102       if (AOP_TYPE(result) != AOP_CRY) 
7103         pic16_outAcc(result);
7104 */
7105       /* leave the result in acc */
7106     }
7107
7108 release:
7109     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7110     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7111     pic16_freeAsmop(result,NULL,ic,TRUE);
7112 }
7113 #endif
7114
7115 /*-----------------------------------------------------------------*/
7116 /* ifxForOp - returns the icode containing the ifx for operand     */
7117 /*-----------------------------------------------------------------*/
7118 static iCode *ifxForOp ( operand *op, iCode *ic )
7119 {
7120   FENTRY2;
7121
7122     /* if true symbol then needs to be assigned */
7123     if (IS_TRUE_SYMOP(op))
7124         return NULL ;
7125
7126     /* if this has register type condition and
7127     the next instruction is ifx with the same operand
7128     and live to of the operand is upto the ifx only then */
7129     if (ic->next
7130         && ic->next->op == IFX
7131         && IC_COND(ic->next)->key == op->key
7132         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7133         ) {
7134                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7135           return ic->next;
7136     }
7137
7138     /*
7139     if (ic->next &&
7140         ic->next->op == IFX &&
7141         IC_COND(ic->next)->key == op->key) {
7142       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7143       return ic->next;
7144     }
7145     */
7146
7147     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7148     if (ic->next &&
7149         ic->next->op == IFX)
7150       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7151
7152     if (ic->next &&
7153         ic->next->op == IFX &&
7154         IC_COND(ic->next)->key == op->key) {
7155       DEBUGpic16_emitcode ("; "," key is okay");
7156       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7157                            OP_SYMBOL(op)->liveTo,
7158                            ic->next->seq);
7159     }
7160
7161 #if 0
7162     /* the code below is completely untested
7163      * it just allows ulong2fs.c compile -- VR */
7164          
7165     ic = ic->next;
7166     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7167                                         __FILE__, __FUNCTION__, __LINE__);
7168         
7169     /* if this has register type condition and
7170     the next instruction is ifx with the same operand
7171     and live to of the operand is upto the ifx only then */
7172     if (ic->next &&
7173         ic->next->op == IFX &&
7174         IC_COND(ic->next)->key == op->key &&
7175         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7176         return ic->next;
7177
7178     if (ic->next &&
7179         ic->next->op == IFX &&
7180         IC_COND(ic->next)->key == op->key) {
7181       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7182       return ic->next;
7183     }
7184
7185     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7186                                         __FILE__, __FUNCTION__, __LINE__);
7187
7188 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7189 #endif
7190
7191     return NULL;
7192 }
7193 /*-----------------------------------------------------------------*/
7194 /* genAndOp - for && operation                                     */
7195 /*-----------------------------------------------------------------*/
7196 static void genAndOp (iCode *ic)
7197 {
7198   operand *left,*right, *result;
7199 /*     symbol *tlbl; */
7200
7201     FENTRY;
7202
7203     /* note here that && operations that are in an
7204     if statement are taken away by backPatchLabels
7205     only those used in arthmetic operations remain */
7206     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7207     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7208     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7209
7210     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7211
7212     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7213     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7214     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7215
7216     /* if both are bit variables */
7217 /*     if (AOP_TYPE(left) == AOP_CRY && */
7218 /*         AOP_TYPE(right) == AOP_CRY ) { */
7219 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7220 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7221 /*         pic16_outBitC(result); */
7222 /*     } else { */
7223 /*         tlbl = newiTempLabel(NULL); */
7224 /*         pic16_toBoolean(left);     */
7225 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7226 /*         pic16_toBoolean(right); */
7227 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7228 /*         pic16_outBitAcc(result); */
7229 /*     } */
7230
7231     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7232     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7233     pic16_freeAsmop(result,NULL,ic,TRUE);
7234 }
7235
7236
7237 /*-----------------------------------------------------------------*/
7238 /* genOrOp - for || operation                                      */
7239 /*-----------------------------------------------------------------*/
7240 /*
7241   tsd pic port -
7242   modified this code, but it doesn't appear to ever get called
7243 */
7244
7245 static void genOrOp (iCode *ic)
7246 {
7247   operand *left,*right, *result;
7248   symbol *tlbl;
7249
7250     FENTRY;  
7251
7252   /* note here that || operations that are in an
7253     if statement are taken away by backPatchLabels
7254     only those used in arthmetic operations remain */
7255     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7256     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7257     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7258
7259     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7260
7261     /* if both are bit variables */
7262     if (AOP_TYPE(left) == AOP_CRY &&
7263         AOP_TYPE(right) == AOP_CRY ) {
7264       pic16_emitcode("clrc","");
7265       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7266                AOP(left)->aopu.aop_dir,
7267                AOP(left)->aopu.aop_dir);
7268       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7269                AOP(right)->aopu.aop_dir,
7270                AOP(right)->aopu.aop_dir);
7271       pic16_emitcode("setc","");
7272
7273     } else {
7274         tlbl = newiTempLabel(NULL);
7275         pic16_toBoolean(left);
7276         emitSKPZ;
7277         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7278         pic16_toBoolean(right);
7279         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7280
7281         pic16_outBitAcc(result);
7282     }
7283
7284     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7285     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7286     pic16_freeAsmop(result,NULL,ic,TRUE);            
7287 }
7288
7289 /*-----------------------------------------------------------------*/
7290 /* isLiteralBit - test if lit == 2^n                               */
7291 /*-----------------------------------------------------------------*/
7292 static int isLiteralBit(unsigned long lit)
7293 {
7294     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7295     0x100L,0x200L,0x400L,0x800L,
7296     0x1000L,0x2000L,0x4000L,0x8000L,
7297     0x10000L,0x20000L,0x40000L,0x80000L,
7298     0x100000L,0x200000L,0x400000L,0x800000L,
7299     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7300     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7301     int idx;
7302     
7303     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7304     for(idx = 0; idx < 32; idx++)
7305         if(lit == pw[idx])
7306             return idx+1;
7307     return 0;
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* continueIfTrue -                                                */
7312 /*-----------------------------------------------------------------*/
7313 static void continueIfTrue (iCode *ic)
7314 {
7315   FENTRY;
7316   if(IC_TRUE(ic))
7317     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7318   ic->generated = 1;
7319 }
7320
7321 /*-----------------------------------------------------------------*/
7322 /* jmpIfTrue -                                                     */
7323 /*-----------------------------------------------------------------*/
7324 static void jumpIfTrue (iCode *ic)
7325 {
7326   FENTRY;
7327   if(!IC_TRUE(ic))
7328     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7329   ic->generated = 1;
7330 }
7331
7332 /*-----------------------------------------------------------------*/
7333 /* jmpTrueOrFalse -                                                */
7334 /*-----------------------------------------------------------------*/
7335 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7336 {
7337   // ugly but optimized by peephole
7338   FENTRY;
7339   if(IC_TRUE(ic)){
7340     symbol *nlbl = newiTempLabel(NULL);
7341       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7342       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7343       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7344       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7345   } else {
7346     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7347     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7348   }
7349   ic->generated = 1;
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* genAnd  - code for and                                          */
7354 /*-----------------------------------------------------------------*/
7355 static void genAnd (iCode *ic, iCode *ifx)
7356 {
7357   operand *left, *right, *result;
7358   int size, offset=0;  
7359   unsigned long lit = 0L;
7360   int bytelit = 0;
7361   resolvedIfx rIfx;
7362
7363     FENTRY;
7364     
7365   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7366   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7367   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7368
7369   resolveIfx(&rIfx,ifx);
7370
7371   /* if left is a literal & right is not then exchange them */
7372   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7373       AOP_NEEDSACC(left)) {
7374     operand *tmp = right ;
7375     right = left;
7376     left = tmp;
7377   }
7378
7379   /* if result = right then exchange them */
7380   if(pic16_sameRegs(AOP(result),AOP(right))){
7381     operand *tmp = right ;
7382     right = left;
7383     left = tmp;
7384   }
7385
7386   /* if right is bit then exchange them */
7387   if (AOP_TYPE(right) == AOP_CRY &&
7388       AOP_TYPE(left) != AOP_CRY){
7389     operand *tmp = right ;
7390     right = left;
7391     left = tmp;
7392   }
7393   if(AOP_TYPE(right) == AOP_LIT)
7394     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7395
7396   size = AOP_SIZE(result);
7397
7398   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7399
7400   // if(bit & yy)
7401   // result = bit & yy;
7402   if (AOP_TYPE(left) == AOP_CRY){
7403     // c = bit & literal;
7404     if(AOP_TYPE(right) == AOP_LIT){
7405       if(lit & 1) {
7406         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7407           // no change
7408           goto release;
7409         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7410       } else {
7411         // bit(result) = 0;
7412         if(size && (AOP_TYPE(result) == AOP_CRY)){
7413           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7414           goto release;
7415         }
7416         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7417           jumpIfTrue(ifx);
7418           goto release;
7419         }
7420         pic16_emitcode("clr","c");
7421       }
7422     } else {
7423       if (AOP_TYPE(right) == AOP_CRY){
7424         // c = bit & bit;
7425         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7426         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427       } else {
7428         // c = bit & val;
7429         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7430         // c = lsb
7431         pic16_emitcode("rrc","a");
7432         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7433       }
7434     }
7435     // bit = c
7436     // val = c
7437     if(size)
7438       pic16_outBitC(result);
7439     // if(bit & ...)
7440     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7441       genIfxJump(ifx, "c");           
7442     goto release ;
7443   }
7444
7445   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7446   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7447   if((AOP_TYPE(right) == AOP_LIT) &&
7448      (AOP_TYPE(result) == AOP_CRY) &&
7449      (AOP_TYPE(left) != AOP_CRY)){
7450     int posbit = isLiteralBit(lit);
7451     /* left &  2^n */
7452     if(posbit){
7453       posbit--;
7454       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7455       // bit = left & 2^n
7456       if(size)
7457         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7458       // if(left &  2^n)
7459       else{
7460         if(ifx){
7461 /*
7462           if(IC_TRUE(ifx)) {
7463             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7464             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7465           } else {
7466             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7467             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7468           }
7469 */
7470         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7471         size = AOP_SIZE(left);
7472
7473         {
7474           int bp = posbit, ofs=0;
7475           
7476             while(bp > 7) {
7477               bp -= 8;
7478               ofs++;
7479             }
7480
7481           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7482                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7483
7484         }
7485 /*
7486           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7487                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7488 */
7489           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7490           
7491           ifx->generated = 1;
7492         }
7493         goto release;
7494       }
7495     } else {
7496       symbol *tlbl = newiTempLabel(NULL);
7497       int sizel = AOP_SIZE(left);
7498
7499       if(size)
7500         emitSETC;
7501
7502       while(sizel--) {
7503         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7504
7505           /* patch provided by Aaron Colwell */
7506           if((posbit = isLiteralBit(bytelit)) != 0) {
7507               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7508                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7509                                                 (posbit-1),0, PO_GPR_REGISTER));
7510
7511               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7512 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7513           } else {
7514               if (bytelit == 0xff) {
7515                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7516                    * a peephole could optimize it out -- VR */
7517                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518               } else {
7519                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7520                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7521               }
7522
7523               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7524                             pic16_popGetLabel(tlbl->key));
7525           }
7526         
7527 #if 0
7528           /* old code, left here for reference -- VR 09/2004 */
7529           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7530           // byte ==  2^n ?
7531           if((posbit = isLiteralBit(bytelit)) != 0)
7532             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7533           else{
7534             if(bytelit != 0x0FFL)
7535               pic16_emitcode("anl","a,%s",
7536                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7537             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7538           }
7539 #endif
7540         }
7541         offset++;
7542       }
7543       // bit = left & literal
7544       if(size) {
7545         emitCLRC;
7546         pic16_emitpLabel(tlbl->key);
7547       }
7548       // if(left & literal)
7549       else {
7550         if(ifx) {
7551           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7552           ifx->generated = 1;
7553         }
7554         pic16_emitpLabel(tlbl->key);
7555         goto release;
7556       }
7557     }
7558
7559     pic16_outBitC(result);
7560     goto release ;
7561   }
7562
7563   /* if left is same as result */
7564   if(pic16_sameRegs(AOP(result),AOP(left))){
7565     int know_W = -1;
7566     for(;size--; offset++,lit>>=8) {
7567       if(AOP_TYPE(right) == AOP_LIT){
7568         switch(lit & 0xff) {
7569         case 0x00:
7570           /*  and'ing with 0 has clears the result */
7571 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7573           break;
7574         case 0xff:
7575           /* and'ing with 0xff is a nop when the result and left are the same */
7576           break;
7577
7578         default:
7579           {
7580             int p = pic16_my_powof2( (~lit) & 0xff );
7581             if(p>=0) {
7582               /* only one bit is set in the literal, so use a bcf instruction */
7583 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7584               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7585
7586             } else {
7587               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7588               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7589               if(know_W != (lit&0xff))
7590                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7591               know_W = lit &0xff;
7592               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7593             }
7594           }    
7595         }
7596       } else {
7597         if (AOP_TYPE(left) == AOP_ACC) {
7598           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7599         } else {                    
7600           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7601           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7602
7603         }
7604       }
7605     }
7606
7607   } else {
7608     // left & result in different registers
7609     if(AOP_TYPE(result) == AOP_CRY){
7610       // result = bit
7611       // if(size), result in bit
7612       // if(!size && ifx), conditional oper: if(left & right)
7613       symbol *tlbl = newiTempLabel(NULL);
7614       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7615       if(size)
7616         pic16_emitcode("setb","c");
7617       while(sizer--){
7618         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7619         pic16_emitcode("anl","a,%s",
7620                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7621         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7622         offset++;
7623       }
7624       if(size){
7625         CLRC;
7626         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7627         pic16_outBitC(result);
7628       } else if(ifx)
7629         jmpTrueOrFalse(ifx, tlbl);
7630     } else {
7631       for(;(size--);offset++) {
7632         // normal case
7633         // result = left & right
7634         if(AOP_TYPE(right) == AOP_LIT){
7635           int t = (lit >> (offset*8)) & 0x0FFL;
7636           switch(t) { 
7637           case 0x00:
7638             pic16_emitcode("clrf","%s",
7639                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7641             break;
7642           case 0xff:
7643             pic16_emitcode("movf","%s,w",
7644                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645             pic16_emitcode("movwf","%s",
7646                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7648             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7649             break;
7650           default:
7651             pic16_emitcode("movlw","0x%x",t);
7652             pic16_emitcode("andwf","%s,w",
7653                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654             pic16_emitcode("movwf","%s",
7655                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7656               
7657             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7658             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7659             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7660           }
7661           continue;
7662         }
7663
7664         if (AOP_TYPE(left) == AOP_ACC) {
7665           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7666           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7667         } else {
7668           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7669           pic16_emitcode("andwf","%s,w",
7670                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7671           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7672           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7673         }
7674         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7675         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7676       }
7677     }
7678   }
7679
7680   release :
7681     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7682   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7683   pic16_freeAsmop(result,NULL,ic,TRUE);     
7684 }
7685
7686 /*-----------------------------------------------------------------*/
7687 /* genOr  - code for or                                            */
7688 /*-----------------------------------------------------------------*/
7689 static void genOr (iCode *ic, iCode *ifx)
7690 {
7691     operand *left, *right, *result;
7692     int size, offset=0;
7693     unsigned long lit = 0L;
7694
7695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7696
7697     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7698     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7699     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7700
7701     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7702
7703     /* if left is a literal & right is not then exchange them */
7704     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7705         AOP_NEEDSACC(left)) {
7706         operand *tmp = right ;
7707         right = left;
7708         left = tmp;
7709     }
7710
7711     /* if result = right then exchange them */
7712     if(pic16_sameRegs(AOP(result),AOP(right))){
7713         operand *tmp = right ;
7714         right = left;
7715         left = tmp;
7716     }
7717
7718     /* if right is bit then exchange them */
7719     if (AOP_TYPE(right) == AOP_CRY &&
7720         AOP_TYPE(left) != AOP_CRY){
7721         operand *tmp = right ;
7722         right = left;
7723         left = tmp;
7724     }
7725
7726     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7727
7728     if(AOP_TYPE(right) == AOP_LIT)
7729         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7730
7731     size = AOP_SIZE(result);
7732
7733     // if(bit | yy)
7734     // xx = bit | yy;
7735     if (AOP_TYPE(left) == AOP_CRY){
7736         if(AOP_TYPE(right) == AOP_LIT){
7737             // c = bit & literal;
7738             if(lit){
7739                 // lit != 0 => result = 1
7740                 if(AOP_TYPE(result) == AOP_CRY){
7741                   if(size)
7742                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7743                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7744                   //     AOP(result)->aopu.aop_dir,
7745                   //     AOP(result)->aopu.aop_dir);
7746                     else if(ifx)
7747                         continueIfTrue(ifx);
7748                     goto release;
7749                 }
7750             } else {
7751                 // lit == 0 => result = left
7752                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7753                     goto release;
7754                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7755             }
7756         } else {
7757             if (AOP_TYPE(right) == AOP_CRY){
7758               if(pic16_sameRegs(AOP(result),AOP(left))){
7759                 // c = bit | bit;
7760                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7761                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7762                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7763
7764                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7765                          AOP(result)->aopu.aop_dir,
7766                          AOP(result)->aopu.aop_dir);
7767                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7768                          AOP(right)->aopu.aop_dir,
7769                          AOP(right)->aopu.aop_dir);
7770                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7771                          AOP(result)->aopu.aop_dir,
7772                          AOP(result)->aopu.aop_dir);
7773               } else {
7774                 if( AOP_TYPE(result) == AOP_ACC) {
7775                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7776                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7779
7780                 } else {
7781
7782                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7783                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7784                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7785                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7786
7787                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7788                                  AOP(result)->aopu.aop_dir,
7789                                  AOP(result)->aopu.aop_dir);
7790                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7791                                  AOP(right)->aopu.aop_dir,
7792                                  AOP(right)->aopu.aop_dir);
7793                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7794                                  AOP(left)->aopu.aop_dir,
7795                                  AOP(left)->aopu.aop_dir);
7796                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7797                                  AOP(result)->aopu.aop_dir,
7798                                  AOP(result)->aopu.aop_dir);
7799                 }
7800               }
7801             } else {
7802                 // c = bit | val;
7803                 symbol *tlbl = newiTempLabel(NULL);
7804                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7805
7806
7807                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7808                 if( AOP_TYPE(right) == AOP_ACC) {
7809                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7810                   emitSKPNZ;
7811                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7812                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7813                 }
7814
7815
7816
7817                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7818                     pic16_emitcode(";XXX setb","c");
7819                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7820                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7821                 pic16_toBoolean(right);
7822                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7823                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7824                     jmpTrueOrFalse(ifx, tlbl);
7825                     goto release;
7826                 } else {
7827                     CLRC;
7828                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7829                 }
7830             }
7831         }
7832         // bit = c
7833         // val = c
7834         if(size)
7835             pic16_outBitC(result);
7836         // if(bit | ...)
7837         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7838             genIfxJump(ifx, "c");           
7839         goto release ;
7840     }
7841
7842     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7843     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7844     if((AOP_TYPE(right) == AOP_LIT) &&
7845        (AOP_TYPE(result) == AOP_CRY) &&
7846        (AOP_TYPE(left) != AOP_CRY)){
7847         if(lit){
7848           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849             // result = 1
7850             if(size)
7851                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7852             else 
7853                 continueIfTrue(ifx);
7854             goto release;
7855         } else {
7856           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7857             // lit = 0, result = boolean(left)
7858             if(size)
7859                 pic16_emitcode(";XXX setb","c");
7860             pic16_toBoolean(right);
7861             if(size){
7862                 symbol *tlbl = newiTempLabel(NULL);
7863                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7864                 CLRC;
7865                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7866             } else {
7867                 genIfxJump (ifx,"a");
7868                 goto release;
7869             }
7870         }
7871         pic16_outBitC(result);
7872         goto release ;
7873     }
7874
7875     /* if left is same as result */
7876     if(pic16_sameRegs(AOP(result),AOP(left))){
7877       int know_W = -1;
7878       for(;size--; offset++,lit>>=8) {
7879         if(AOP_TYPE(right) == AOP_LIT){
7880           if((lit & 0xff) == 0)
7881             /*  or'ing with 0 has no effect */
7882             continue;
7883           else {
7884             int p = pic16_my_powof2(lit & 0xff);
7885             if(p>=0) {
7886               /* only one bit is set in the literal, so use a bsf instruction */
7887               pic16_emitpcode(POC_BSF,
7888                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7889             } else {
7890               if(know_W != (lit & 0xff))
7891                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7892               know_W = lit & 0xff;
7893               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7894             }
7895                     
7896           }
7897         } else {
7898           if (AOP_TYPE(left) == AOP_ACC) {
7899             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7900 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7901           } else {                  
7902             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7903             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7904
7905 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7906 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907
7908           }
7909         }
7910       }
7911     } else {
7912         // left & result in different registers
7913         if(AOP_TYPE(result) == AOP_CRY){
7914             // result = bit
7915             // if(size), result in bit
7916             // if(!size && ifx), conditional oper: if(left | right)
7917             symbol *tlbl = newiTempLabel(NULL);
7918             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7919             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7920
7921
7922             if(size)
7923                 pic16_emitcode(";XXX setb","c");
7924             while(sizer--){
7925                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926                 pic16_emitcode(";XXX orl","a,%s",
7927                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7929                 offset++;
7930             }
7931             if(size){
7932                 CLRC;
7933                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7934                 pic16_outBitC(result);
7935             } else if(ifx)
7936                 jmpTrueOrFalse(ifx, tlbl);
7937         } else for(;(size--);offset++){
7938           // normal case
7939           // result = left & right
7940           if(AOP_TYPE(right) == AOP_LIT){
7941             int t = (lit >> (offset*8)) & 0x0FFL;
7942             switch(t) { 
7943             case 0x00:
7944               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7945               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7946
7947 //            pic16_emitcode("movf","%s,w",
7948 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7949 //            pic16_emitcode("movwf","%s",
7950 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7951               break;
7952             default:
7953               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7954               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7955               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7956
7957 //            pic16_emitcode("movlw","0x%x",t);
7958 //            pic16_emitcode("iorwf","%s,w",
7959 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7960 //            pic16_emitcode("movwf","%s",
7961 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7962               
7963             }
7964             continue;
7965           }
7966
7967           // faster than result <- left, anl result,right
7968           // and better if result is SFR
7969           if (AOP_TYPE(left) == AOP_ACC) {
7970             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7971 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7972           } else {
7973             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7974             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7975
7976 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7977 //          pic16_emitcode("iorwf","%s,w",
7978 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7979           }
7980           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7981 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7982         }
7983     }
7984
7985 release :
7986     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7987     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7988     pic16_freeAsmop(result,NULL,ic,TRUE);     
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* genXor - code for xclusive or                                   */
7993 /*-----------------------------------------------------------------*/
7994 static void genXor (iCode *ic, iCode *ifx)
7995 {
7996   operand *left, *right, *result;
7997   int size, offset=0;
7998   unsigned long lit = 0L;
7999
8000   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8001
8002   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8003   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8004   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8005
8006   /* if left is a literal & right is not ||
8007      if left needs acc & right does not */
8008   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8009       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8010     operand *tmp = right ;
8011     right = left;
8012     left = tmp;
8013   }
8014
8015   /* if result = right then exchange them */
8016   if(pic16_sameRegs(AOP(result),AOP(right))){
8017     operand *tmp = right ;
8018     right = left;
8019     left = tmp;
8020   }
8021
8022   /* if right is bit then exchange them */
8023   if (AOP_TYPE(right) == AOP_CRY &&
8024       AOP_TYPE(left) != AOP_CRY){
8025     operand *tmp = right ;
8026     right = left;
8027     left = tmp;
8028   }
8029   if(AOP_TYPE(right) == AOP_LIT)
8030     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8031
8032   size = AOP_SIZE(result);
8033
8034   // if(bit ^ yy)
8035   // xx = bit ^ yy;
8036   if (AOP_TYPE(left) == AOP_CRY){
8037     if(AOP_TYPE(right) == AOP_LIT){
8038       // c = bit & literal;
8039       if(lit>>1){
8040         // lit>>1  != 0 => result = 1
8041         if(AOP_TYPE(result) == AOP_CRY){
8042           if(size)
8043             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8044             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8045           else if(ifx)
8046             continueIfTrue(ifx);
8047           goto release;
8048         }
8049         pic16_emitcode("setb","c");
8050       } else{
8051         // lit == (0 or 1)
8052         if(lit == 0){
8053           // lit == 0, result = left
8054           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8055             goto release;
8056           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8057         } else{
8058           // lit == 1, result = not(left)
8059           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8060             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8061             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8062             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8063             goto release;
8064           } else {
8065             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8066             pic16_emitcode("cpl","c");
8067           }
8068         }
8069       }
8070
8071     } else {
8072       // right != literal
8073       symbol *tlbl = newiTempLabel(NULL);
8074       if (AOP_TYPE(right) == AOP_CRY){
8075         // c = bit ^ bit;
8076         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8077       }
8078       else{
8079         int sizer = AOP_SIZE(right);
8080         // c = bit ^ val
8081         // if val>>1 != 0, result = 1
8082         pic16_emitcode("setb","c");
8083         while(sizer){
8084           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8085           if(sizer == 1)
8086             // test the msb of the lsb
8087             pic16_emitcode("anl","a,#0xfe");
8088           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8089           sizer--;
8090         }
8091         // val = (0,1)
8092         pic16_emitcode("rrc","a");
8093       }
8094       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8095       pic16_emitcode("cpl","c");
8096       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8097     }
8098     // bit = c
8099     // val = c
8100     if(size)
8101       pic16_outBitC(result);
8102     // if(bit | ...)
8103     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8104       genIfxJump(ifx, "c");           
8105     goto release ;
8106   }
8107
8108   if(pic16_sameRegs(AOP(result),AOP(left))){
8109     /* if left is same as result */
8110     for(;size--; offset++) {
8111       if(AOP_TYPE(right) == AOP_LIT){
8112         int t  = (lit >> (offset*8)) & 0x0FFL;
8113         if(t == 0x00L)
8114           continue;
8115         else
8116           if (IS_AOP_PREG(left)) {
8117             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119             pic16_aopPut(AOP(result),"a",offset);
8120           } else {
8121             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8122             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8123             pic16_emitcode("xrl","%s,%s",
8124                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8125                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126           }
8127       } else {
8128         if (AOP_TYPE(left) == AOP_ACC)
8129           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8130         else {
8131           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8132           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8133 /*
8134           if (IS_AOP_PREG(left)) {
8135             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136             pic16_aopPut(AOP(result),"a",offset);
8137           } else
8138             pic16_emitcode("xrl","%s,a",
8139                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8140 */
8141         }
8142       }
8143     }
8144   } else {
8145     // left & result in different registers
8146     if(AOP_TYPE(result) == AOP_CRY){
8147       // result = bit
8148       // if(size), result in bit
8149       // if(!size && ifx), conditional oper: if(left ^ right)
8150       symbol *tlbl = newiTempLabel(NULL);
8151       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8152       if(size)
8153         pic16_emitcode("setb","c");
8154       while(sizer--){
8155         if((AOP_TYPE(right) == AOP_LIT) &&
8156            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8157           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158         } else {
8159           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8160           pic16_emitcode("xrl","a,%s",
8161                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8162         }
8163         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8164         offset++;
8165       }
8166       if(size){
8167         CLRC;
8168         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8169         pic16_outBitC(result);
8170       } else if(ifx)
8171         jmpTrueOrFalse(ifx, tlbl);
8172     } else for(;(size--);offset++){
8173       // normal case
8174       // result = left & right
8175       if(AOP_TYPE(right) == AOP_LIT){
8176         int t = (lit >> (offset*8)) & 0x0FFL;
8177         switch(t) { 
8178         case 0x00:
8179           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8180           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181           pic16_emitcode("movf","%s,w",
8182                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183           pic16_emitcode("movwf","%s",
8184                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185           break;
8186         case 0xff:
8187           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8188           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189           pic16_emitcode("comf","%s,w",
8190                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191           pic16_emitcode("movwf","%s",
8192                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193           break;
8194         default:
8195           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8196           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8197           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8198           pic16_emitcode("movlw","0x%x",t);
8199           pic16_emitcode("xorwf","%s,w",
8200                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8201           pic16_emitcode("movwf","%s",
8202                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8203
8204         }
8205         continue;
8206       }
8207
8208       // faster than result <- left, anl result,right
8209       // and better if result is SFR
8210       if (AOP_TYPE(left) == AOP_ACC) {
8211         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8212         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213       } else {
8214         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8215         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8216         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8218       }
8219       if ( AOP_TYPE(result) != AOP_ACC){
8220         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8221         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8222       }
8223     }
8224   }
8225
8226   release :
8227     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8228   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229   pic16_freeAsmop(result,NULL,ic,TRUE);     
8230 }
8231
8232 /*-----------------------------------------------------------------*/
8233 /* genInline - write the inline code out                           */
8234 /*-----------------------------------------------------------------*/
8235 static void genInline (iCode *ic)
8236 {
8237   char *buffer, *bp, *bp1;
8238     
8239         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8240
8241         _G.inLine += (!options.asmpeep);
8242
8243         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8244         strcpy(buffer,IC_INLINE(ic));
8245         
8246         while((bp1=strstr(bp, "\\n"))) {
8247           *bp1++ = '\n';
8248           *bp1++ = ' ';
8249           bp = bp1;
8250         }
8251         bp = bp1 = buffer;
8252
8253 #if 0
8254   /* This is an experimental code for #pragma inline
8255      and is temporarily disabled for 2.5.0 release */
8256         if(asmInlineMap)
8257         {
8258           symbol *sym;
8259           char *s;
8260           char *cbuf;
8261           int cblen;
8262
8263             cbuf = Safe_strdup(buffer);
8264             cblen = strlen(buffer)+1;
8265             memset(cbuf, 0, cblen);
8266
8267             bp = buffer;
8268             bp1 = cbuf;
8269             while(*bp) {
8270               if(*bp != '%')*bp1++ = *bp++;
8271               else {
8272                 int i;
8273
8274                   bp++;
8275                   i = *bp - '0';
8276                   if(i>elementsInSet(asmInlineMap))break;
8277                   
8278                   bp++;
8279                   s = indexSet(asmInlineMap, i);
8280                   DEBUGpc("searching symbol s = `%s'", s);
8281                   sym = findSym(SymbolTab, NULL, s);
8282
8283                   if(sym->reqv) {
8284                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8285                   } else {
8286                     strcat(bp1, sym->rname);
8287                   }
8288                   
8289                   while(*bp1)bp1++;
8290               }
8291               
8292               if(strlen(bp1) > cblen - 16) {
8293                 int i = strlen(cbuf);
8294                 cblen += 50;
8295                 cbuf = realloc(cbuf, cblen);
8296                 memset(cbuf+i, 0, 50);
8297                 bp1 = cbuf + i;
8298               }
8299             }
8300             
8301             free(buffer);
8302             buffer = Safe_strdup( cbuf );
8303             free(cbuf);
8304             
8305             bp = bp1 = buffer;
8306         }
8307 #endif  /* 0 */
8308
8309         /* emit each line as a code */
8310         while (*bp) {
8311                 if (*bp == '\n') {
8312                         *bp++ = '\0';
8313
8314                         if(*bp1)
8315                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8316                         bp1 = bp;
8317                 } else {
8318                         if (*bp == ':') {
8319                                 bp++;
8320                                 *bp = '\0';
8321                                 bp++;
8322
8323                                 /* print label, use this special format with NULL directive
8324                                  * to denote that the argument should not be indented with tab */
8325                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326                                 bp1 = bp;
8327                         } if (*bp == ';') {
8328                                 /* advance to end of line (prevent splitting of comments at ':' */
8329                                 while (*bp && *bp != '\n') {
8330                                         bp++;
8331                                 } // while
8332                         } else
8333                                 bp++;
8334                 }
8335         }
8336
8337         if ((bp1 != bp) && *bp1)
8338                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8339
8340
8341     Safe_free(buffer);
8342
8343     _G.inLine -= (!options.asmpeep);
8344 }
8345
8346 /*-----------------------------------------------------------------*/
8347 /* genRRC - rotate right with carry                                */
8348 /*-----------------------------------------------------------------*/
8349 static void genRRC (iCode *ic)
8350 {
8351   operand *left , *result ;
8352   int size, offset = 0, same;
8353
8354   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8355
8356   /* rotate right with carry */
8357   left = IC_LEFT(ic);
8358   result=IC_RESULT(ic);
8359   pic16_aopOp (left,ic,FALSE);
8360   pic16_aopOp (result,ic,TRUE);
8361
8362   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8363
8364   same = pic16_sameRegs(AOP(result),AOP(left));
8365
8366   size = AOP_SIZE(result);    
8367
8368   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8369
8370   /* get the lsb and put it into the carry */
8371   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8372
8373   offset = 0 ;
8374
8375   while(size--) {
8376
8377     if(same) {
8378       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8379     } else {
8380       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8382     }
8383
8384     offset++;
8385   }
8386
8387   pic16_freeAsmop(left,NULL,ic,TRUE);
8388   pic16_freeAsmop(result,NULL,ic,TRUE);
8389 }
8390
8391 /*-----------------------------------------------------------------*/
8392 /* genRLC - generate code for rotate left with carry               */
8393 /*-----------------------------------------------------------------*/
8394 static void genRLC (iCode *ic)
8395 {    
8396   operand *left , *result ;
8397   int size, offset = 0;
8398   int same;
8399
8400   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8401   /* rotate right with carry */
8402   left = IC_LEFT(ic);
8403   result=IC_RESULT(ic);
8404   pic16_aopOp (left,ic,FALSE);
8405   pic16_aopOp (result,ic,TRUE);
8406
8407   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8408
8409   same = pic16_sameRegs(AOP(result),AOP(left));
8410
8411   /* move it to the result */
8412   size = AOP_SIZE(result);    
8413
8414   /* get the msb and put it into the carry */
8415   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8416
8417   offset = 0 ;
8418
8419   while(size--) {
8420
8421     if(same) {
8422       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8423     } else {
8424       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8425       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8426     }
8427
8428     offset++;
8429   }
8430
8431
8432   pic16_freeAsmop(left,NULL,ic,TRUE);
8433   pic16_freeAsmop(result,NULL,ic,TRUE);
8434 }
8435
8436
8437 /* gpasm can get the highest order bit with HIGH/UPPER
8438  * so the following probably is not needed -- VR */
8439  
8440 /*-----------------------------------------------------------------*/
8441 /* genGetHbit - generates code get highest order bit               */
8442 /*-----------------------------------------------------------------*/
8443 static void genGetHbit (iCode *ic)
8444 {
8445     operand *left, *result;
8446     left = IC_LEFT(ic);
8447     result=IC_RESULT(ic);
8448     pic16_aopOp (left,ic,FALSE);
8449     pic16_aopOp (result,ic,FALSE);
8450
8451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8452     /* get the highest order byte into a */
8453     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8454     if(AOP_TYPE(result) == AOP_CRY){
8455         pic16_emitcode("rlc","a");
8456         pic16_outBitC(result);
8457     }
8458     else{
8459         pic16_emitcode("rl","a");
8460         pic16_emitcode("anl","a,#0x01");
8461         pic16_outAcc(result);
8462     }
8463
8464
8465     pic16_freeAsmop(left,NULL,ic,TRUE);
8466     pic16_freeAsmop(result,NULL,ic,TRUE);
8467 }
8468
8469 #if 0
8470 /*-----------------------------------------------------------------*/
8471 /* AccRol - rotate left accumulator by known count                 */
8472 /*-----------------------------------------------------------------*/
8473 static void AccRol (int shCount)
8474 {
8475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8476     shCount &= 0x0007;              // shCount : 0..7
8477     switch(shCount){
8478         case 0 :
8479             break;
8480         case 1 :
8481             pic16_emitcode("rl","a");
8482             break;
8483         case 2 :
8484             pic16_emitcode("rl","a");
8485             pic16_emitcode("rl","a");
8486             break;
8487         case 3 :
8488             pic16_emitcode("swap","a");
8489             pic16_emitcode("rr","a");
8490             break;
8491         case 4 :
8492             pic16_emitcode("swap","a");
8493             break;
8494         case 5 :
8495             pic16_emitcode("swap","a");
8496             pic16_emitcode("rl","a");
8497             break;
8498         case 6 :
8499             pic16_emitcode("rr","a");
8500             pic16_emitcode("rr","a");
8501             break;
8502         case 7 :
8503             pic16_emitcode("rr","a");
8504             break;
8505     }
8506 }
8507 #endif
8508
8509 /*-----------------------------------------------------------------*/
8510 /* AccLsh - left shift accumulator by known count                  */
8511 /*-----------------------------------------------------------------*/
8512 static void AccLsh (int shCount, int doMask)
8513 {
8514         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8515         switch(shCount){
8516                 case 0 :
8517                         return;
8518                         break;
8519                 case 1 :
8520                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 2 :
8523                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 3 :
8527                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 4 :
8531                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533                 case 5 :
8534                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8535                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536                         break;
8537                 case 6 :
8538                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8540                         break;
8541                 case 7 :
8542                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543                         break;
8544         }
8545         if (doMask) {
8546                 /* no masking is required in genPackBits */
8547                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8548         }
8549 }
8550
8551 /*-----------------------------------------------------------------*/
8552 /* AccRsh - right shift accumulator by known count                 */
8553 /*-----------------------------------------------------------------*/
8554 static void AccRsh (int shCount, int andmask)
8555 {
8556         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8557         switch(shCount){
8558                 case 0 :
8559                         return; break;
8560                 case 1 :
8561                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563                 case 2 :
8564                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566                         break;
8567                 case 3 :
8568                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8569                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570                         break;
8571                 case 4 :
8572                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8573                         break;
8574                 case 5 :
8575                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8576                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8577                         break;
8578                 case 6 :
8579                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8580                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8581                         break;
8582                 case 7 :
8583                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8584                         break;
8585         }
8586         
8587         if(andmask)
8588                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8589         else
8590                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8591 }
8592
8593 #if 0
8594 /*-----------------------------------------------------------------*/
8595 /* AccSRsh - signed right shift accumulator by known count                 */
8596 /*-----------------------------------------------------------------*/
8597 static void AccSRsh (int shCount)
8598 {
8599     symbol *tlbl ;
8600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8601     if(shCount != 0){
8602         if(shCount == 1){
8603             pic16_emitcode("mov","c,acc.7");
8604             pic16_emitcode("rrc","a");
8605         } else if(shCount == 2){
8606             pic16_emitcode("mov","c,acc.7");
8607             pic16_emitcode("rrc","a");
8608             pic16_emitcode("mov","c,acc.7");
8609             pic16_emitcode("rrc","a");
8610         } else {
8611             tlbl = newiTempLabel(NULL);
8612             /* rotate right accumulator */
8613             AccRol(8 - shCount);
8614             /* and kill the higher order bits */
8615             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8616             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8617             pic16_emitcode("orl","a,#0x%02x",
8618                      (unsigned char)~SRMask[shCount]);
8619             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8620         }
8621     }
8622 }
8623 #endif
8624
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR1Left2Result - shift right one byte from left to result   */
8627 /*-----------------------------------------------------------------*/
8628 static void shiftR1Left2ResultSigned (operand *left, int offl,
8629                                 operand *result, int offr,
8630                                 int shCount)
8631 {
8632   int same;
8633
8634   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8635
8636   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8637
8638   switch(shCount) {
8639   case 1:
8640     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8641     if(same) 
8642       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8643     else {
8644       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8646     }
8647
8648     break;
8649   case 2:
8650
8651     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8652     if(same) 
8653       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8654     else {
8655       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8657     }
8658     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8659     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8660
8661     break;
8662
8663   case 3:
8664     if(same)
8665       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8666     else {
8667       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669     }
8670
8671     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8672     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8673     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8674
8675     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8677
8678     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8679     break;
8680
8681   case 4:
8682     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8687     break;
8688   case 5:
8689     if(same) {
8690       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8691     } else {
8692       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8693       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8694     }
8695     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8696     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8697     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8698     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8699     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8700     break;
8701
8702   case 6:
8703     if(same) {
8704       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8705       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8707       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8708       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8710     } else {
8711       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8712       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8714       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8716     }
8717     break;
8718
8719   case 7:
8720     if(same) {
8721       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8722       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8723       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8724       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8725     } else {
8726       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8727       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8728       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8729     }
8730
8731   default:
8732     break;
8733   }
8734 }
8735
8736 /*-----------------------------------------------------------------*/
8737 /* shiftR1Left2Result - shift right one byte from left to result   */
8738 /*-----------------------------------------------------------------*/
8739 static void shiftR1Left2Result (operand *left, int offl,
8740                                 operand *result, int offr,
8741                                 int shCount, int sign)
8742 {
8743   int same;
8744
8745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746
8747   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8748
8749   /* Copy the msb into the carry if signed. */
8750   if(sign) {
8751     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8752     return;
8753   }
8754
8755
8756
8757   switch(shCount) {
8758   case 1:
8759     emitCLRC;
8760     if(same) 
8761       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762     else {
8763       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8765     }
8766     break;
8767   case 2:
8768     emitCLRC;
8769     if(same) {
8770       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8771     } else {
8772       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8773       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774     }
8775     emitCLRC;
8776     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8777
8778     break;
8779   case 3:
8780     if(same)
8781       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8782     else {
8783       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8784       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785     }
8786
8787     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8788     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8790     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791     break;
8792       
8793   case 4:
8794     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8795     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8796     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8797     break;
8798
8799   case 5:
8800     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8802     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803     //emitCLRC;
8804     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8805
8806     break;
8807   case 6:
8808
8809     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8810     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8811     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8812     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8813     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8814     break;
8815
8816   case 7:
8817
8818     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8819     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8820     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8821
8822     break;
8823
8824   default:
8825     break;
8826   }
8827 }
8828
8829 /*-----------------------------------------------------------------*/
8830 /* shiftL1Left2Result - shift left one byte from left to result    */
8831 /*-----------------------------------------------------------------*/
8832 static void shiftL1Left2Result (operand *left, int offl,
8833                                 operand *result, int offr, int shCount)
8834 {
8835   int same;
8836
8837   //    char *l;
8838   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839
8840   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8841   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8842     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8843     //    MOVA(l);
8844     /* shift left accumulator */
8845     //AccLsh(shCount, 1); // don't comment out just yet...
8846   //    pic16_aopPut(AOP(result),"a",offr);
8847
8848   switch(shCount) {
8849   case 1:
8850     /* Shift left 1 bit position */
8851     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8852     if(same) {
8853       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8854     } else {
8855       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8857     }
8858     break;
8859   case 2:
8860     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8861     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8864     break;
8865   case 3:
8866     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8867     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8868     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8871     break;
8872   case 4:
8873     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8874     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8876     break;
8877   case 5:
8878     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8879     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8880     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8881     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8882     break;
8883   case 6:
8884     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8885     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8886     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8887     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8888     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8889     break;
8890   case 7:
8891     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8893     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8894     break;
8895
8896   default:
8897     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8898   }
8899
8900 }
8901
8902 /*-----------------------------------------------------------------*/
8903 /* movLeft2Result - move byte from left to result                  */
8904 /*-----------------------------------------------------------------*/
8905 static void movLeft2Result (operand *left, int offl,
8906                             operand *result, int offr)
8907 {
8908   char *l;
8909   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8910   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8911     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8912
8913     if (*l == '@' && (IS_AOP_PREG(result))) {
8914       pic16_emitcode("mov","a,%s",l);
8915       pic16_aopPut(AOP(result),"a",offr);
8916     } else {
8917       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919     }
8920   }
8921 }
8922
8923 /*-----------------------------------------------------------------*/
8924 /* shiftL2Left2Result - shift left two bytes from left to result   */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftL2Left2Result (operand *left, int offl,
8927                                 operand *result, int offr, int shCount)
8928 {
8929   int same = pic16_sameRegs(AOP(result), AOP(left));
8930   int i;
8931
8932   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8933
8934   if (same && (offl != offr)) { // shift bytes
8935     if (offr > offl) {
8936        for(i=1;i>-1;i--) {
8937          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8938          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8939        }
8940     } else { // just treat as different later on
8941                 same = 0;
8942     }
8943   }
8944
8945   if(same) {
8946     switch(shCount) {
8947     case 0:
8948       break;
8949     case 1:
8950     case 2:
8951     case 3:
8952
8953       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8955       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8956
8957       while(--shCount) {
8958                 emitCLRC;
8959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8961       }
8962
8963       break;
8964     case 4:
8965     case 5:
8966       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8967       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8968       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8973       if(shCount >=5) {
8974                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8975                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8976       }
8977       break;
8978     case 6:
8979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8980       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8981       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8984       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8985       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8987       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8988       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8989       break;
8990     case 7:
8991       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8992       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8993       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8994       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8995       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8996     }
8997
8998   } else {
8999     switch(shCount) {
9000     case 0:
9001       break;
9002     case 1:
9003     case 2:
9004     case 3:
9005       /* note, use a mov/add for the shift since the mov has a
9006          chance of getting optimized out */
9007       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9010       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012
9013       while(--shCount) {
9014                 emitCLRC;
9015                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9016                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9017       }
9018       break;
9019
9020     case 4:
9021     case 5:
9022       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9023       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9026       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9028       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9030
9031
9032       if(shCount == 5) {
9033                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9034                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9035       }
9036       break;
9037     case 6:
9038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9041       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9042
9043       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9046       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9047       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9049       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9051       break;
9052     case 7:
9053       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9054       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9055       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9056       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9057       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9058     }
9059   }
9060
9061 }
9062 /*-----------------------------------------------------------------*/
9063 /* shiftR2Left2Result - shift right two bytes from left to result  */
9064 /*-----------------------------------------------------------------*/
9065 static void shiftR2Left2Result (operand *left, int offl,
9066                                 operand *result, int offr,
9067                                 int shCount, int sign)
9068 {
9069   int same = pic16_sameRegs(AOP(result), AOP(left));
9070   int i;
9071   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9072
9073   if (same && (offl != offr)) { // shift right bytes
9074     if (offr < offl) {
9075        for(i=0;i<2;i++) {
9076          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9077          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9078        }
9079     } else { // just treat as different later on
9080                 same = 0;
9081     }
9082   }
9083
9084   switch(shCount) {
9085   case 0:
9086     break;
9087   case 1:
9088   case 2:
9089   case 3:
9090     if(sign)
9091       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9092     else
9093       emitCLRC;
9094
9095     if(same) {
9096       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9098     } else {
9099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9101       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9102       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9103     }
9104
9105     while(--shCount) {
9106       if(sign)
9107                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9108       else
9109                 emitCLRC;
9110       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9112     }
9113     break;
9114   case 4:
9115   case 5:
9116     if(same) {
9117
9118       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9119       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9120       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9121
9122       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9123       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9124       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9125       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9126     } else {
9127       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9128       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9129       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9130
9131       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9132       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9133       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9134       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9135       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9136     }
9137
9138     if(shCount >=5) {
9139       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9140       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9141     }
9142
9143     if(sign) {
9144       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9145       pic16_emitpcode(POC_BTFSC, 
9146                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9147       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9148     }
9149
9150     break;
9151
9152   case 6:
9153     if(same) {
9154
9155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9157
9158       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9159       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9160       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9161       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9162       if(sign) {
9163         pic16_emitpcode(POC_BTFSC, 
9164                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9165         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9166       }
9167       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9168       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9169       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9170       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9171     } else {
9172       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9174       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9175       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9176       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9177       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9178       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9179       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9180       if(sign) {
9181         pic16_emitpcode(POC_BTFSC, 
9182                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9183         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9184       }
9185       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9186       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9187
9188         
9189     }
9190
9191     break;
9192   case 7:
9193     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9194     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9195     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9196     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9197     if(sign) {
9198       emitSKPNC;
9199       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9200     } else 
9201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9202   }
9203 }
9204
9205
9206 /*-----------------------------------------------------------------*/
9207 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9208 /*-----------------------------------------------------------------*/
9209 static void shiftLLeftOrResult (operand *left, int offl,
9210                                 operand *result, int offr, int shCount)
9211 {
9212     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9213
9214     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9215     /* shift left accumulator */
9216     AccLsh(shCount, 1);
9217     /* or with result */
9218     /* back to result */
9219     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9220 }
9221
9222 /*-----------------------------------------------------------------*/
9223 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9224 /*-----------------------------------------------------------------*/
9225 static void shiftRLeftOrResult (operand *left, int offl,
9226                                 operand *result, int offr, int shCount)
9227 {
9228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9229     
9230     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9231     /* shift right accumulator */
9232     AccRsh(shCount, 1);
9233     /* or with result */
9234     /* back to result */
9235     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* genlshOne - left shift a one byte quantity by known count       */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshOne (operand *result, operand *left, int shCount)
9242 {       
9243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9244     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9245 }
9246
9247 /*-----------------------------------------------------------------*/
9248 /* genlshTwo - left shift two bytes by known amount != 0           */
9249 /*-----------------------------------------------------------------*/
9250 static void genlshTwo (operand *result,operand *left, int shCount)
9251 {
9252     int size;
9253     
9254     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9255     size = pic16_getDataSize(result);
9256
9257     /* if shCount >= 8 */
9258     if (shCount >= 8) {
9259         shCount -= 8 ;
9260
9261         if (size > 1){
9262             if (shCount)
9263                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9264             else 
9265                 movLeft2Result(left, LSB, result, MSB16);
9266         }
9267         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9268     }
9269
9270     /*  1 <= shCount <= 7 */
9271     else {  
9272         if(size == 1)
9273             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9274         else 
9275             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9276     }
9277 }
9278
9279 /*-----------------------------------------------------------------*/
9280 /* shiftLLong - shift left one long from left to result            */
9281 /* offr = LSB or MSB16                                             */
9282 /*-----------------------------------------------------------------*/
9283 static void shiftLLong (operand *left, operand *result, int offr )
9284 {
9285     int size = AOP_SIZE(result);
9286     int same = pic16_sameRegs(AOP(left),AOP(result));
9287         int i;
9288
9289     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9290
9291         if (same && (offr == MSB16)) { //shift one byte
9292                 for(i=size-1;i>=MSB16;i--) {
9293                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9294                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9295                 }
9296         } else {
9297                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9298         }
9299         
9300     if (size > LSB+offr ){
9301                 if (same) {
9302                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9303                 } else {
9304                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9305                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9306                 }
9307          }
9308
9309     if(size > MSB16+offr){
9310                 if (same) {
9311                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9312                 } else {
9313                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9314                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9315                 }
9316     }
9317
9318     if(size > MSB24+offr){
9319                 if (same) {
9320                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9321                 } else {
9322                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9323                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9324                 }
9325     }
9326
9327     if(size > MSB32+offr){
9328                 if (same) {
9329                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9330                 } else {
9331                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9332                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9333                 }
9334     }
9335     if(offr != LSB)
9336                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9337
9338 }
9339
9340 /*-----------------------------------------------------------------*/
9341 /* genlshFour - shift four byte by a known amount != 0             */
9342 /*-----------------------------------------------------------------*/
9343 static void genlshFour (operand *result, operand *left, int shCount)
9344 {
9345     int size;
9346
9347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9348     size = AOP_SIZE(result);
9349
9350     /* if shifting more that 3 bytes */
9351     if (shCount >= 24 ) {
9352         shCount -= 24;
9353         if (shCount)
9354             /* lowest order of left goes to the highest
9355             order of the destination */
9356             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9357         else
9358             movLeft2Result(left, LSB, result, MSB32);
9359
9360                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9361                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9362                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9363
9364         return;
9365     }
9366
9367     /* more than two bytes */
9368     else if ( shCount >= 16 ) {
9369         /* lower order two bytes goes to higher order two bytes */
9370         shCount -= 16;
9371         /* if some more remaining */
9372         if (shCount)
9373             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9374         else {
9375             movLeft2Result(left, MSB16, result, MSB32);
9376             movLeft2Result(left, LSB, result, MSB24);
9377         }
9378                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9379                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9380         return;
9381     }    
9382
9383     /* if more than 1 byte */
9384     else if ( shCount >= 8 ) {
9385         /* lower order three bytes goes to higher order  three bytes */
9386         shCount -= 8;
9387         if(size == 2){
9388             if(shCount)
9389                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9390             else
9391                 movLeft2Result(left, LSB, result, MSB16);
9392         }
9393         else{   /* size = 4 */
9394             if(shCount == 0){
9395                 movLeft2Result(left, MSB24, result, MSB32);
9396                 movLeft2Result(left, MSB16, result, MSB24);
9397                 movLeft2Result(left, LSB, result, MSB16);
9398                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9399             }
9400             else if(shCount == 1)
9401                 shiftLLong(left, result, MSB16);
9402             else{
9403                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9404                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9405                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9406                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9407             }
9408         }
9409     }
9410
9411     /* 1 <= shCount <= 7 */
9412     else if(shCount <= 3)
9413     { 
9414         shiftLLong(left, result, LSB);
9415         while(--shCount >= 1)
9416             shiftLLong(result, result, LSB);
9417     }
9418     /* 3 <= shCount <= 7, optimize */
9419     else{
9420         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9421         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9422         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9423     }
9424 }
9425
9426 /*-----------------------------------------------------------------*/
9427 /* genLeftShiftLiteral - left shifting by known count              */
9428 /*-----------------------------------------------------------------*/
9429 void pic16_genLeftShiftLiteral (operand *left,
9430                                  operand *right,
9431                                  operand *result,
9432                                  iCode *ic)
9433 {    
9434     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9435     int size;
9436
9437     FENTRY;
9438     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9439     pic16_freeAsmop(right,NULL,ic,TRUE);
9440
9441     pic16_aopOp(left,ic,FALSE);
9442     pic16_aopOp(result,ic,TRUE);
9443
9444     size = getSize(operandType(result));
9445
9446 #if VIEW_SIZE
9447     pic16_emitcode("; shift left ","result %d, left %d",size,
9448              AOP_SIZE(left));
9449 #endif
9450
9451     /* I suppose that the left size >= result size */
9452     if(shCount == 0){
9453         while(size--){
9454             movLeft2Result(left, size, result, size);
9455         }
9456     }
9457
9458     else if(shCount >= (size * 8))
9459         while(size--)
9460             pic16_aopPut(AOP(result),zero,size);
9461     else{
9462         switch (size) {
9463             case 1:
9464                 genlshOne (result,left,shCount);
9465                 break;
9466
9467             case 2:
9468             case 3:
9469                 genlshTwo (result,left,shCount);
9470                 break;
9471
9472             case 4:
9473                 genlshFour (result,left,shCount);
9474                 break;
9475         }
9476     }
9477     pic16_freeAsmop(left,NULL,ic,TRUE);
9478     pic16_freeAsmop(result,NULL,ic,TRUE);
9479 }
9480
9481 /*-----------------------------------------------------------------*
9482  * genMultiAsm - repeat assembly instruction for size of register.
9483  * if endian == 1, then the high byte (i.e base address + size of 
9484  * register) is used first else the low byte is used first;
9485  *-----------------------------------------------------------------*/
9486 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9487 {
9488
9489   int offset = 0;
9490
9491   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9492
9493   if(!reg)
9494     return;
9495
9496   if(!endian) {
9497     endian = 1;
9498   } else {
9499     endian = -1;
9500     offset = size-1;
9501   }
9502
9503   while(size--) {
9504     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9505     offset += endian;
9506   }
9507
9508 }
9509
9510 #if !(USE_GENERIC_SIGNED_SHIFT)
9511 /*-----------------------------------------------------------------*/
9512 /* genLeftShift - generates code for left shifting                 */
9513 /*-----------------------------------------------------------------*/
9514 static void genLeftShift (iCode *ic)
9515 {
9516   operand *left,*right, *result;
9517   int size, offset;
9518 //  char *l;
9519   symbol *tlbl , *tlbl1;
9520   pCodeOp *pctemp;
9521
9522   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9523
9524   right = IC_RIGHT(ic);
9525   left  = IC_LEFT(ic);
9526   result = IC_RESULT(ic);
9527
9528   pic16_aopOp(right,ic,FALSE);
9529
9530   /* if the shift count is known then do it 
9531      as efficiently as possible */
9532   if (AOP_TYPE(right) == AOP_LIT) {
9533     pic16_genLeftShiftLiteral (left,right,result,ic);
9534     return ;
9535   }
9536
9537   /* shift count is unknown then we have to form
9538    * a loop. Get the loop count in WREG : Note: we take
9539    * only the lower order byte since shifting
9540    * more than 32 bits make no sense anyway, ( the
9541    * largest size of an object can be only 32 bits ) */
9542   
9543   pic16_aopOp(left,ic,FALSE);
9544   pic16_aopOp(result,ic,FALSE);
9545
9546   /* now move the left to the result if they are not the
9547    * same, and if size > 1,
9548    * and if right is not same to result (!!!) -- VR */
9549   if (!pic16_sameRegs(AOP(left),AOP(result))
9550       && (AOP_SIZE(result) > 1)) {
9551
9552     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9553
9554     size = AOP_SIZE(result);
9555     offset=0;
9556     while (size--) {
9557
9558 #if 0
9559       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9560       if (*l == '@' && (IS_AOP_PREG(result))) {
9561
9562           pic16_emitcode("mov","a,%s",l);
9563           pic16_aopPut(AOP(result),"a",offset);
9564       } else
9565 #endif
9566       {
9567         /* we don't know if left is a literal or a register, take care -- VR */
9568         pic16_mov2f(AOP(result), AOP(left), offset);
9569       }
9570       offset++;
9571     }
9572   }
9573
9574   size = AOP_SIZE(result);
9575
9576   /* if it is only one byte then */
9577   if (size == 1) {
9578     if(optimized_for_speed) {
9579       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9580       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9581       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9582       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9583       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9584       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9585       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9586       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9587       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9588       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9589       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9590       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9591     } else {
9592
9593       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9594
9595       tlbl = newiTempLabel(NULL);
9596
9597 #if 1
9598       /* this is already done, why change it? */
9599       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9600                 pic16_mov2f(AOP(result), AOP(left), 0);
9601       }
9602 #endif
9603
9604       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9605       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9606       pic16_emitpLabel(tlbl->key);
9607       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9608       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9609       emitSKPC;
9610       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9611     }
9612     goto release ;
9613   }
9614     
9615   if (pic16_sameRegs(AOP(left),AOP(result))) {
9616
9617     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9618     
9619     tlbl = newiTempLabel(NULL);
9620     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9621     genMultiAsm(POC_RRCF, result, size,1);
9622     pic16_emitpLabel(tlbl->key);
9623     genMultiAsm(POC_RLCF, result, size,0);
9624     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9625     emitSKPC;
9626     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9627     goto release;
9628   }
9629
9630   //tlbl = newiTempLabel(NULL);
9631   //offset = 0 ;   
9632   //tlbl1 = newiTempLabel(NULL);
9633
9634   //reAdjustPreg(AOP(result));    
9635     
9636   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9637   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9638   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9639   //MOVA(l);
9640   //pic16_emitcode("add","a,acc");         
9641   //pic16_aopPut(AOP(result),"a",offset++);
9642   //while (--size) {
9643   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9644   //  MOVA(l);
9645   //  pic16_emitcode("rlc","a");         
9646   //  pic16_aopPut(AOP(result),"a",offset++);
9647   //}
9648   //reAdjustPreg(AOP(result));
9649
9650   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9651   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9652
9653
9654   tlbl = newiTempLabel(NULL);
9655   tlbl1= newiTempLabel(NULL);
9656
9657   size = AOP_SIZE(result);
9658   offset = 1;
9659
9660   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9661
9662   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9663
9664   /* offset should be 0, 1 or 3 */
9665   
9666   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9667   emitSKPNZ;
9668   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9669
9670   pic16_emitpcode(POC_MOVWF, pctemp);
9671
9672
9673   pic16_emitpLabel(tlbl->key);
9674
9675   emitCLRC;
9676   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9677   while(--size)
9678     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9679
9680   pic16_emitpcode(POC_DECFSZ,  pctemp);
9681   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9682   pic16_emitpLabel(tlbl1->key);
9683
9684   pic16_popReleaseTempReg(pctemp,1);
9685
9686
9687  release:
9688   pic16_freeAsmop (right,NULL,ic,TRUE);
9689   pic16_freeAsmop(left,NULL,ic,TRUE);
9690   pic16_freeAsmop(result,NULL,ic,TRUE);
9691 }
9692 #endif
9693
9694
9695 #if 0
9696 #error old code (left here for reference)
9697 /*-----------------------------------------------------------------*/
9698 /* genLeftShift - generates code for left shifting                 */
9699 /*-----------------------------------------------------------------*/
9700 static void genLeftShift (iCode *ic)
9701 {
9702   operand *left,*right, *result;
9703   int size, offset;
9704   char *l;
9705   symbol *tlbl , *tlbl1;
9706   pCodeOp *pctemp;
9707
9708   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9709
9710   right = IC_RIGHT(ic);
9711   left  = IC_LEFT(ic);
9712   result = IC_RESULT(ic);
9713
9714   pic16_aopOp(right,ic,FALSE);
9715
9716   /* if the shift count is known then do it 
9717      as efficiently as possible */
9718   if (AOP_TYPE(right) == AOP_LIT) {
9719     pic16_genLeftShiftLiteral (left,right,result,ic);
9720     return ;
9721   }
9722
9723   /* shift count is unknown then we have to form 
9724      a loop get the loop count in B : Note: we take
9725      only the lower order byte since shifting
9726      more that 32 bits make no sense anyway, ( the
9727      largest size of an object can be only 32 bits ) */  
9728
9729     
9730   pic16_aopOp(left,ic,FALSE);
9731   pic16_aopOp(result,ic,FALSE);
9732
9733   /* now move the left to the result if they are not the
9734      same */
9735   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9736       AOP_SIZE(result) > 1) {
9737
9738     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9739
9740     size = AOP_SIZE(result);
9741     offset=0;
9742     while (size--) {
9743       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9744       if (*l == '@' && (IS_AOP_PREG(result))) {
9745
9746         pic16_emitcode("mov","a,%s",l);
9747         pic16_aopPut(AOP(result),"a",offset);
9748       } else {
9749
9750         /* we don't know if left is a literal or a register, take care -- VR */
9751         pic16_mov2f(AOP(result), AOP(left), offset);
9752       }
9753       offset++;
9754     }
9755   }
9756
9757   size = AOP_SIZE(result);
9758
9759   /* if it is only one byte then */
9760   if (size == 1) {
9761     if(optimized_for_speed) {
9762       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9763       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9764       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9765       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9766       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9767       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9768       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9769       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9770       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9771       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9772       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9773       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9774     } else {
9775
9776       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9777
9778       tlbl = newiTempLabel(NULL);
9779       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9780                 pic16_mov2f(AOP(result), AOP(left), 0);
9781                 
9782 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9783 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9784       }
9785
9786       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9787       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9788       pic16_emitpLabel(tlbl->key);
9789       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9790       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9791       emitSKPC;
9792       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9793     }
9794     goto release ;
9795   }
9796     
9797   if (pic16_sameRegs(AOP(left),AOP(result))) {
9798
9799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9800     
9801     tlbl = newiTempLabel(NULL);
9802     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9803     genMultiAsm(POC_RRCF, result, size,1);
9804     pic16_emitpLabel(tlbl->key);
9805     genMultiAsm(POC_RLCF, result, size,0);
9806     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9807     emitSKPC;
9808     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9809     goto release;
9810   }
9811
9812   //tlbl = newiTempLabel(NULL);
9813   //offset = 0 ;   
9814   //tlbl1 = newiTempLabel(NULL);
9815
9816   //reAdjustPreg(AOP(result));    
9817     
9818   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9819   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9820   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9821   //MOVA(l);
9822   //pic16_emitcode("add","a,acc");         
9823   //pic16_aopPut(AOP(result),"a",offset++);
9824   //while (--size) {
9825   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9826   //  MOVA(l);
9827   //  pic16_emitcode("rlc","a");         
9828   //  pic16_aopPut(AOP(result),"a",offset++);
9829   //}
9830   //reAdjustPreg(AOP(result));
9831
9832   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9833   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9834
9835
9836   tlbl = newiTempLabel(NULL);
9837   tlbl1= newiTempLabel(NULL);
9838
9839   size = AOP_SIZE(result);
9840   offset = 1;
9841
9842   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9843
9844   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9845
9846   /* offset should be 0, 1 or 3 */
9847   
9848   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9849   emitSKPNZ;
9850   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9851
9852   pic16_emitpcode(POC_MOVWF, pctemp);
9853
9854
9855   pic16_emitpLabel(tlbl->key);
9856
9857   emitCLRC;
9858   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9859   while(--size)
9860     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9861
9862   pic16_emitpcode(POC_DECFSZ,  pctemp);
9863   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9864   pic16_emitpLabel(tlbl1->key);
9865
9866   pic16_popReleaseTempReg(pctemp,1);
9867
9868
9869  release:
9870   pic16_freeAsmop (right,NULL,ic,TRUE);
9871   pic16_freeAsmop(left,NULL,ic,TRUE);
9872   pic16_freeAsmop(result,NULL,ic,TRUE);
9873 }
9874 #endif
9875
9876 /*-----------------------------------------------------------------*/
9877 /* genrshOne - right shift a one byte quantity by known count      */
9878 /*-----------------------------------------------------------------*/
9879 static void genrshOne (operand *result, operand *left,
9880                        int shCount, int sign)
9881 {
9882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9883     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9884 }
9885
9886 /*-----------------------------------------------------------------*/
9887 /* genrshTwo - right shift two bytes by known amount != 0          */
9888 /*-----------------------------------------------------------------*/
9889 static void genrshTwo (operand *result,operand *left,
9890                        int shCount, int sign)
9891 {
9892   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9893   /* if shCount >= 8 */
9894   if (shCount >= 8) {
9895     shCount -= 8 ;
9896     if (shCount)
9897       shiftR1Left2Result(left, MSB16, result, LSB,
9898                          shCount, sign);
9899     else
9900       movLeft2Result(left, MSB16, result, LSB);
9901
9902     pic16_addSign (result, 1, sign);
9903   }
9904
9905   /*  1 <= shCount <= 7 */
9906   else
9907     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9908 }
9909
9910 /*-----------------------------------------------------------------*/
9911 /* shiftRLong - shift right one long from left to result           */
9912 /* offl = LSB or MSB16                                             */
9913 /*-----------------------------------------------------------------*/
9914 static void shiftRLong (operand *left, int offl,
9915                         operand *result, int sign)
9916 {
9917     int size = AOP_SIZE(result);
9918     int same = pic16_sameRegs(AOP(left),AOP(result));
9919     int i;
9920     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9921
9922         if (same && (offl == MSB16)) { //shift one byte right
9923                 for(i=MSB16;i<size;i++) {
9924                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9925                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9926                 }
9927         }
9928
9929     if(sign)
9930                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9931         else
9932                 emitCLRC;
9933
9934         if (same) {
9935                 if (offl == LSB)
9936                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9937         } else {
9938         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9939         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9940         }
9941
9942     if(offl == MSB16) {
9943         /* add sign of "a" */
9944         pic16_addSign(result, MSB32, sign);
9945         }
9946
9947         if (same) {
9948         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9949         } else {
9950         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9951         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9952         }
9953         
9954         if (same) {
9955         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9956         } else {
9957         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9958         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9959         }
9960
9961         if (same) {
9962         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9963         } else {
9964         if(offl == LSB){
9965                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9966                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9967         }
9968         }
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genrshFour - shift four byte by a known amount != 0             */
9973 /*-----------------------------------------------------------------*/
9974 static void genrshFour (operand *result, operand *left,
9975                         int shCount, int sign)
9976 {
9977   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9978   /* if shifting more that 3 bytes */
9979   if(shCount >= 24 ) {
9980     shCount -= 24;
9981     if(shCount)
9982       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9983     else
9984       movLeft2Result(left, MSB32, result, LSB);
9985
9986     pic16_addSign(result, MSB16, sign);
9987   }
9988   else if(shCount >= 16){
9989     shCount -= 16;
9990     if(shCount)
9991       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9992     else{
9993       movLeft2Result(left, MSB24, result, LSB);
9994       movLeft2Result(left, MSB32, result, MSB16);
9995     }
9996     pic16_addSign(result, MSB24, sign);
9997   }
9998   else if(shCount >= 8){
9999     shCount -= 8;
10000     if(shCount == 1)
10001       shiftRLong(left, MSB16, result, sign);
10002     else if(shCount == 0){
10003       movLeft2Result(left, MSB16, result, LSB);
10004       movLeft2Result(left, MSB24, result, MSB16);
10005       movLeft2Result(left, MSB32, result, MSB24);
10006       pic16_addSign(result, MSB32, sign);
10007     }
10008     else{ //shcount >= 2
10009       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10010       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10011       /* the last shift is signed */
10012       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10013       pic16_addSign(result, MSB32, sign);
10014     }
10015   }
10016   else{   /* 1 <= shCount <= 7 */
10017     if(shCount <= 2){
10018       shiftRLong(left, LSB, result, sign);
10019       if(shCount == 2)
10020         shiftRLong(result, LSB, result, sign);
10021     }
10022     else{
10023       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10024       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10025       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10026     }
10027   }
10028 }
10029
10030 /*-----------------------------------------------------------------*/
10031 /* genRightShiftLiteral - right shifting by known count            */
10032 /*-----------------------------------------------------------------*/
10033 static void genRightShiftLiteral (operand *left,
10034                                   operand *right,
10035                                   operand *result,
10036                                   iCode *ic,
10037                                   int sign)
10038 {    
10039   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10040   int lsize,res_size;
10041
10042   pic16_freeAsmop(right,NULL,ic,TRUE);
10043
10044   pic16_aopOp(left,ic,FALSE);
10045   pic16_aopOp(result,ic,TRUE);
10046
10047   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10048
10049 #if VIEW_SIZE
10050   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10051                  AOP_SIZE(left));
10052 #endif
10053
10054   lsize = pic16_getDataSize(left);
10055   res_size = pic16_getDataSize(result);
10056   /* test the LEFT size !!! */
10057
10058   /* I suppose that the left size >= result size */
10059   if(shCount == 0){
10060     assert (res_size <= lsize);
10061     while (res_size--) {
10062       pic16_mov2f (AOP(result), AOP(left), res_size);
10063     } // for
10064   }
10065
10066   else if(shCount >= (lsize * 8)){
10067
10068     if(res_size == 1) {
10069       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10070       if(sign) {
10071         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10072         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10073       }
10074     } else {
10075
10076       if(sign) {
10077         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10078         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10079         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10080         while(res_size--)
10081           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10082
10083       } else {
10084
10085         while(res_size--)
10086           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10087       }
10088     }
10089   } else {
10090
10091     switch (res_size) {
10092     case 1:
10093       genrshOne (result,left,shCount,sign);
10094       break;
10095
10096     case 2:
10097       genrshTwo (result,left,shCount,sign);
10098       break;
10099
10100     case 4:
10101       genrshFour (result,left,shCount,sign);
10102       break;
10103     default :
10104       break;
10105     }
10106
10107   }
10108
10109   pic16_freeAsmop(left,NULL,ic,TRUE);
10110   pic16_freeAsmop(result,NULL,ic,TRUE);
10111 }
10112
10113 #if !(USE_GENERIC_SIGNED_SHIFT)
10114 /*-----------------------------------------------------------------*/
10115 /* genSignedRightShift - right shift of signed number              */
10116 /*-----------------------------------------------------------------*/
10117 static void genSignedRightShift (iCode *ic)
10118 {
10119   operand *right, *left, *result;
10120   int size, offset;
10121   //  char *l;
10122   symbol *tlbl, *tlbl1 ;
10123   pCodeOp *pctemp;
10124
10125   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10126
10127   /* we do it the hard way put the shift count in b
10128      and loop thru preserving the sign */
10129   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10130
10131   right = IC_RIGHT(ic);
10132   left  = IC_LEFT(ic);
10133   result = IC_RESULT(ic);
10134
10135   pic16_aopOp(right,ic,FALSE);  
10136   pic16_aopOp(left,ic,FALSE);
10137   pic16_aopOp(result,ic,FALSE);
10138
10139
10140   if ( AOP_TYPE(right) == AOP_LIT) {
10141     genRightShiftLiteral (left,right,result,ic,1);
10142     return ;
10143   }
10144   /* shift count is unknown then we have to form 
10145      a loop get the loop count in B : Note: we take
10146      only the lower order byte since shifting
10147      more that 32 bits make no sense anyway, ( the
10148      largest size of an object can be only 32 bits ) */  
10149
10150   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10151   //pic16_emitcode("inc","b");
10152   //pic16_freeAsmop (right,NULL,ic,TRUE);
10153   //pic16_aopOp(left,ic,FALSE);
10154   //pic16_aopOp(result,ic,FALSE);
10155
10156   /* now move the left to the result if they are not the
10157      same */
10158   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10159       AOP_SIZE(result) > 1) {
10160
10161     size = AOP_SIZE(result);
10162     offset=0;
10163     while (size--) { 
10164       /*
10165         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10166         if (*l == '@' && IS_AOP_PREG(result)) {
10167
10168         pic16_emitcode("mov","a,%s",l);
10169         pic16_aopPut(AOP(result),"a",offset);
10170         } else
10171         pic16_aopPut(AOP(result),l,offset);
10172       */
10173       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10174       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10175
10176       offset++;
10177     }
10178   }
10179
10180   /* mov the highest order bit to OVR */    
10181   tlbl = newiTempLabel(NULL);
10182   tlbl1= newiTempLabel(NULL);
10183
10184   size = AOP_SIZE(result);
10185   offset = size - 1;
10186
10187   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10188
10189   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10190
10191   /* offset should be 0, 1 or 3 */
10192   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10193   emitSKPNZ;
10194   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10195
10196   pic16_emitpcode(POC_MOVWF, pctemp);
10197
10198
10199   pic16_emitpLabel(tlbl->key);
10200
10201   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10202   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10203
10204   while(--size) {
10205     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10206   }
10207
10208   pic16_emitpcode(POC_DECFSZ,  pctemp);
10209   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10210   pic16_emitpLabel(tlbl1->key);
10211
10212   pic16_popReleaseTempReg(pctemp,1);
10213 #if 0
10214   size = AOP_SIZE(result);
10215   offset = size - 1;
10216   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10217   pic16_emitcode("rlc","a");
10218   pic16_emitcode("mov","ov,c");
10219   /* if it is only one byte then */
10220   if (size == 1) {
10221     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10222     MOVA(l);
10223     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10224     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10225     pic16_emitcode("mov","c,ov");
10226     pic16_emitcode("rrc","a");
10227     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10228     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10229     pic16_aopPut(AOP(result),"a",0);
10230     goto release ;
10231   }
10232
10233   reAdjustPreg(AOP(result));
10234   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10235   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10236   pic16_emitcode("mov","c,ov");
10237   while (size--) {
10238     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10239     MOVA(l);
10240     pic16_emitcode("rrc","a");         
10241     pic16_aopPut(AOP(result),"a",offset--);
10242   }
10243   reAdjustPreg(AOP(result));
10244   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10245   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10246
10247  release:
10248 #endif
10249
10250   pic16_freeAsmop(left,NULL,ic,TRUE);
10251   pic16_freeAsmop(result,NULL,ic,TRUE);
10252   pic16_freeAsmop(right,NULL,ic,TRUE);
10253 }
10254 #endif
10255
10256 #if !(USE_GENERIC_SIGNED_SHIFT)
10257 #warning This implementation of genRightShift() is incomplete!
10258 /*-----------------------------------------------------------------*/
10259 /* genRightShift - generate code for right shifting                */
10260 /*-----------------------------------------------------------------*/
10261 static void genRightShift (iCode *ic)
10262 {
10263     operand *right, *left, *result;
10264     sym_link *letype ;
10265     int size, offset;
10266     char *l;
10267     symbol *tlbl, *tlbl1 ;
10268
10269     /* if signed then we do it the hard way preserve the
10270     sign bit moving it inwards */
10271     letype = getSpec(operandType(IC_LEFT(ic)));
10272     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10273
10274     if (!SPEC_USIGN(letype)) {
10275         genSignedRightShift (ic);
10276         return ;
10277     }
10278
10279     /* signed & unsigned types are treated the same : i.e. the
10280     signed is NOT propagated inwards : quoting from the
10281     ANSI - standard : "for E1 >> E2, is equivalent to division
10282     by 2**E2 if unsigned or if it has a non-negative value,
10283     otherwise the result is implementation defined ", MY definition
10284     is that the sign does not get propagated */
10285
10286     right = IC_RIGHT(ic);
10287     left  = IC_LEFT(ic);
10288     result = IC_RESULT(ic);
10289
10290     pic16_aopOp(right,ic,FALSE);
10291
10292     /* if the shift count is known then do it 
10293     as efficiently as possible */
10294     if (AOP_TYPE(right) == AOP_LIT) {
10295         genRightShiftLiteral (left,right,result,ic, 0);
10296         return ;
10297     }
10298
10299     /* shift count is unknown then we have to form 
10300     a loop get the loop count in B : Note: we take
10301     only the lower order byte since shifting
10302     more that 32 bits make no sense anyway, ( the
10303     largest size of an object can be only 32 bits ) */  
10304
10305     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10306     pic16_emitcode("inc","b");
10307     pic16_aopOp(left,ic,FALSE);
10308     pic16_aopOp(result,ic,FALSE);
10309
10310     /* now move the left to the result if they are not the
10311     same */
10312     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10313         AOP_SIZE(result) > 1) {
10314
10315         size = AOP_SIZE(result);
10316         offset=0;
10317         while (size--) {
10318             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10319             if (*l == '@' && IS_AOP_PREG(result)) {
10320
10321                 pic16_emitcode("mov","a,%s",l);
10322                 pic16_aopPut(AOP(result),"a",offset);
10323             } else
10324                 pic16_aopPut(AOP(result),l,offset);
10325             offset++;
10326         }
10327     }
10328
10329     tlbl = newiTempLabel(NULL);
10330     tlbl1= newiTempLabel(NULL);
10331     size = AOP_SIZE(result);
10332     offset = size - 1;
10333
10334     /* if it is only one byte then */
10335     if (size == 1) {
10336
10337       tlbl = newiTempLabel(NULL);
10338       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10339         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10340         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10341       }
10342
10343       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10344       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10345       pic16_emitpLabel(tlbl->key);
10346       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10347       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10348       emitSKPC;
10349       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10350
10351       goto release ;
10352     }
10353
10354     reAdjustPreg(AOP(result));
10355     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10356     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10357     CLRC;
10358     while (size--) {
10359         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10360         MOVA(l);
10361         pic16_emitcode("rrc","a");         
10362         pic16_aopPut(AOP(result),"a",offset--);
10363     }
10364     reAdjustPreg(AOP(result));
10365
10366     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10367     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10368
10369 release:
10370     pic16_freeAsmop(left,NULL,ic,TRUE);
10371     pic16_freeAsmop (right,NULL,ic,TRUE);
10372     pic16_freeAsmop(result,NULL,ic,TRUE);
10373 }
10374 #endif
10375
10376 #if (USE_GENERIC_SIGNED_SHIFT)
10377 /*-----------------------------------------------------------------*/
10378 /* genGenericShift - generates code for left or right shifting     */
10379 /*-----------------------------------------------------------------*/
10380 static void genGenericShift (iCode *ic, int isShiftLeft) {
10381   operand *left,*right, *result;
10382   int offset;
10383   int sign, signedCount;
10384   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10385   PIC_OPCODE pos_shift, neg_shift;
10386
10387   FENTRY;
10388
10389   right = IC_RIGHT(ic);
10390   left  = IC_LEFT(ic);
10391   result = IC_RESULT(ic);
10392
10393   pic16_aopOp(right,ic,FALSE);
10394   pic16_aopOp(left,ic,FALSE);
10395   pic16_aopOp(result,ic,TRUE);
10396
10397   sign = !SPEC_USIGN(operandType (left));
10398   signedCount = !SPEC_USIGN(operandType (right));
10399
10400   /* if the shift count is known then do it 
10401      as efficiently as possible */
10402   if (AOP_TYPE(right) == AOP_LIT) {
10403     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10404     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10405     // we should modify right->aopu.aop_lit here!
10406     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10407     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10408     if (isShiftLeft)
10409       pic16_genLeftShiftLiteral (left,right,result,ic);
10410     else
10411       genRightShiftLiteral (left,right,result,ic, sign);
10412
10413     goto release;
10414   } // if (right is literal)
10415
10416   /* shift count is unknown then we have to form a loop.
10417    * Note: we take only the lower order byte since shifting
10418    * more than 32 bits make no sense anyway, ( the
10419    * largest size of an object can be only 32 bits )
10420    * Note: we perform arithmetic shifts if the left operand is
10421    * signed and we do an (effective) right shift, i. e. we
10422    * shift in the sign bit from the left. */
10423    
10424   label_complete = newiTempLabel ( NULL );
10425   label_loop_pos = newiTempLabel ( NULL );
10426   label_loop_neg = NULL;
10427   label_negative = NULL;
10428   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10429   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10430
10431   if (signedCount) {
10432     // additional labels needed
10433     label_loop_neg = newiTempLabel ( NULL );
10434     label_negative = newiTempLabel ( NULL );
10435   } // if
10436
10437   // copy source to result -- this will effectively truncate the left operand to the size of result!
10438   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10439   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10440   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10441     pic16_mov2f (AOP(result),AOP(left), offset);
10442   } // for
10443
10444   // if result is longer than left, fill with zeros (or sign)
10445   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10446     if (sign && AOP_SIZE(left) > 0) {
10447       // shift signed operand -- fill with sign
10448       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10449       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10450       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10451       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10452         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10453       } // for
10454     } else {
10455       // shift unsigned operand -- fill result with zeros
10456       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10457         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10458       } // for
10459     }
10460   } // if (size mismatch)
10461
10462   pic16_mov2w (AOP(right), 0);
10463   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10464   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10465   
10466 #if 0
10467   // perform a shift by one (shift count is positive)
10468   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10469   // 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])
10470   pic16_emitpLabel (label_loop_pos->key);
10471   emitCLRC;
10472   if (sign && (pos_shift == POC_RRCF)) {
10473     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10474     emitSETC;
10475   } // if
10476   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10477   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10478   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10479 #else
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]+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])
10483   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10484   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10485   emitCLRC;
10486   pic16_emitpLabel (label_loop_pos->key);
10487   if (sign && (pos_shift == POC_RRCF)) {
10488     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10489     emitSETC;
10490   } // if
10491   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10492   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10493   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10494   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10495 #endif
10496
10497   if (signedCount) {
10498     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10499
10500     pic16_emitpLabel (label_negative->key);
10501     // perform a shift by -1 (shift count is negative)
10502     // 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)
10503     emitCLRC;
10504     pic16_emitpLabel (label_loop_neg->key);
10505     if (sign && (neg_shift == POC_RRCF)) {
10506       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10507       emitSETC;
10508     } // if
10509     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10510     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10511     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10512     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10513   } // if (signedCount)
10514
10515   pic16_emitpLabel (label_complete->key);
10516
10517 release:
10518   pic16_freeAsmop (right,NULL,ic,TRUE);
10519   pic16_freeAsmop(left,NULL,ic,TRUE);
10520   pic16_freeAsmop(result,NULL,ic,TRUE);
10521 }
10522
10523 static void genLeftShift (iCode *ic) {
10524   genGenericShift (ic, 1);
10525 }
10526
10527 static void genRightShift (iCode *ic) {
10528   genGenericShift (ic, 0);
10529 }
10530 #endif
10531
10532
10533 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10534 void pic16_loadFSR0(operand *op, int lit)
10535 {
10536   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10537     if (AOP_TYPE(op) == AOP_LIT) {
10538       /* handle 12 bit integers correctly */
10539       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10540       if ((val & 0x0fff) != val) {
10541         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10542                 val, (val & 0x0fff) );
10543         val &= 0x0fff;
10544       }
10545       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10546     } else {
10547       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10548     }
10549   } else {
10550     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10551     // set up FSR0 with address of result
10552     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10553     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10554   }
10555 }
10556
10557 /*----------------------------------------------------------------*/
10558 /* pic16_derefPtr - move one byte from the location ptr points to */
10559 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10560 /*                  to the location ptr points to (doWrite != 0)   */
10561 /*----------------------------------------------------------------*/
10562 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10563 {
10564   if (!IS_PTR(operandType(ptr)))
10565   {
10566     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10567     else pic16_mov2w (AOP(ptr), 0);
10568     return;
10569   }
10570
10571   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10572   /* We might determine pointer type right here: */
10573   p_type = DCL_TYPE(operandType(ptr));
10574
10575   switch (p_type) {
10576     case FPOINTER:
10577     case POINTER:
10578       if (!fsr0_setup || !*fsr0_setup)
10579       {
10580         pic16_loadFSR0( ptr, 0 );
10581         if (fsr0_setup) *fsr0_setup = 1;
10582       }
10583       if (doWrite)
10584         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10585       else
10586         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10587       break;
10588
10589     case GPOINTER:
10590       if (AOP(ptr)->aopu.aop_reg[2]) {
10591         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10592         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10593         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10594         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10595         pic16_mov2w(AOP(ptr), 2);
10596         pic16_callGenericPointerRW(doWrite, 1);
10597       } else {
10598         // data pointer (just 2 byte given)
10599         if (!fsr0_setup || !*fsr0_setup)
10600         {
10601           pic16_loadFSR0( ptr, 0 );
10602           if (fsr0_setup) *fsr0_setup = 1;
10603         }
10604         if (doWrite)
10605           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10606         else
10607           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10608       }
10609       break;
10610
10611     default:
10612       assert (0 && "invalid pointer type specified");
10613       break;
10614   }
10615 }
10616
10617 /*-----------------------------------------------------------------*/
10618 /* genUnpackBits - generates code for unpacking bits               */
10619 /*-----------------------------------------------------------------*/
10620 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10621 {    
10622   int shCnt ;
10623   sym_link *etype, *letype;
10624   int blen=0, bstr=0;
10625   int lbstr;
10626   int same;
10627   pCodeOp *op;
10628
10629   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10630   etype = getSpec(operandType(result));
10631   letype = getSpec(operandType(left));
10632
10633   //    if(IS_BITFIELD(etype)) {
10634   blen = SPEC_BLEN(etype);
10635   bstr = SPEC_BSTR(etype);
10636   //    }
10637
10638   lbstr = SPEC_BSTR( letype );
10639
10640   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10641       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10642
10643 #if 1
10644   if((blen == 1) && (bstr < 8)
10645       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10646     /* it is a single bit, so use the appropriate bit instructions */
10647     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10648
10649     same = pic16_sameRegs(AOP(left),AOP(result));
10650     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10651     pic16_emitpcode(POC_CLRF, op);
10652
10653     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10654       /* workaround to reduce the extra lfsr instruction */
10655       pic16_emitpcode(POC_BTFSC,
10656           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10657     } else {
10658       assert (PIC_IS_DATA_PTR (operandType(left)));
10659       pic16_loadFSR0 (left, 0);
10660       pic16_emitpcode(POC_BTFSC,
10661           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10662     }
10663
10664     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10665       /* unsigned bitfields result in either 0 or 1 */
10666       pic16_emitpcode(POC_INCF, op);
10667     } else {
10668       /* signed bitfields result in either 0 or -1 */
10669       pic16_emitpcode(POC_DECF, op);
10670     }
10671     if (same) {
10672       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10673     }
10674
10675     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10676     return;
10677   }
10678
10679 #endif
10680
10681   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10682     // access symbol directly
10683     pic16_mov2w (AOP(left), 0);
10684   } else {
10685     pic16_derefPtr (left, ptype, 0, NULL);
10686   }
10687
10688   /* if we have bitdisplacement then it fits   */
10689   /* into this byte completely or if length is */
10690   /* less than a byte                          */
10691   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10692
10693     /* shift right acc */
10694     AccRsh(shCnt, 0);
10695
10696     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10697           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10698
10699     /* VR -- normally I would use the following, but since we use the hack,
10700      * to avoid the masking from AccRsh, why not mask it right now? */
10701
10702     /*
10703        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10704      */
10705
10706     /* extend signed bitfields to 8 bits */
10707     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10708     {
10709       assert (blen + bstr > 0);
10710       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10711       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10712     }
10713
10714     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10715
10716     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10717     return ;
10718   }
10719
10720   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10721   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10722   exit(-1);
10723
10724   return ;
10725 }
10726
10727
10728 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10729 {
10730   int size, offset = 0, leoffset=0 ;
10731
10732         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10733         pic16_aopOp(result, ic, TRUE);
10734
10735         FENTRY;
10736
10737         size = AOP_SIZE(result);
10738 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10739
10740
10741 #if 1
10742         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10743                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10744                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10745                 goto release;
10746         }
10747 #endif
10748
10749         if(AOP(left)->aopu.pcop->type == PO_DIR)
10750                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10751
10752         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10753
10754         while (size--) {
10755                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10756                 
10757 //              pic16_DumpOp("(result)",result);
10758                 if(is_LitAOp(AOP(result))) {
10759                         pic16_mov2w(AOP(left), offset); // patch 8
10760                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10761                 } else {
10762                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10763                                 pic16_popGet(AOP(left), offset), //patch 8
10764                                 pic16_popGet(AOP(result), offset)));
10765                 }
10766
10767                 offset++;
10768                 leoffset++;
10769         }
10770
10771 release:
10772     pic16_freeAsmop(result,NULL,ic,TRUE);
10773 }
10774
10775
10776
10777 /*-----------------------------------------------------------------*/
10778 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10779 /*-----------------------------------------------------------------*/
10780 static void genNearPointerGet (operand *left, 
10781                                operand *result, 
10782                                iCode *ic)
10783 {
10784 //  asmop *aop = NULL;
10785   //regs *preg = NULL ;
10786   sym_link *rtype, *retype;
10787   sym_link *ltype, *letype;
10788
10789     FENTRY;
10790     
10791     rtype = operandType(result);
10792     retype= getSpec(rtype);
10793     ltype = operandType(left);
10794     letype= getSpec(ltype);
10795     
10796     pic16_aopOp(left,ic,FALSE);
10797
10798 //    pic16_DumpOp("(left)",left);
10799 //    pic16_DumpOp("(result)",result);
10800
10801     /* if left is rematerialisable and
10802      * result is not bit variable type and
10803      * the left is pointer to data space i.e
10804      * lower 128 bytes of space */
10805     
10806     if (AOP_TYPE(left) == AOP_PCODE
10807       && !IS_BITFIELD(retype)
10808       && DCL_TYPE(ltype) == POINTER) {
10809
10810         genDataPointerGet (left,result,ic);
10811         pic16_freeAsmop(left, NULL, ic, TRUE);
10812         return ;
10813     }
10814     
10815     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10816     pic16_aopOp (result,ic,TRUE);
10817     
10818     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10819
10820 #if 1
10821     if(IS_BITFIELD( retype )
10822       && (SPEC_BLEN(operandType(result))==1)
10823     ) {
10824       iCode *nextic;
10825       pCodeOp *jop;
10826       int bitstrt, bytestrt;
10827
10828         /* if this is bitfield of size 1, see if we are checking the value
10829          * of a single bit in an if-statement,
10830          * if yes, then don't generate usual code, but execute the
10831          * genIfx directly -- VR */
10832
10833         nextic = ic->next;
10834
10835         /* CHECK: if next iCode is IFX
10836          * and current result operand is nextic's conditional operand
10837          * and current result operand live ranges ends at nextic's key number
10838          */
10839         if((nextic->op == IFX)
10840           && (result == IC_COND(nextic))
10841           && (OP_LIVETO(result) == nextic->seq)
10842           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10843           ) {
10844             /* everything is ok then */
10845             /* find a way to optimize the genIfx iCode */
10846
10847             bytestrt = SPEC_BSTR(operandType(result))/8;
10848             bitstrt = SPEC_BSTR(operandType(result))%8;
10849             
10850             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10851
10852             genIfxpCOpJump(nextic, jop);
10853             
10854             pic16_freeAsmop(left, NULL, ic, TRUE);
10855             pic16_freeAsmop(result, NULL, ic, TRUE);
10856             return;
10857         }
10858     }
10859 #endif
10860
10861     /* if bitfield then unpack the bits */
10862     if (IS_BITFIELD(letype)) 
10863       genUnpackBits (result, left, NULL, POINTER);
10864     else {
10865       /* we have can just get the values */
10866       int size = AOP_SIZE(result);
10867       int offset = 0;   
10868         
10869       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10870
10871       pic16_loadFSR0( left, 0 );
10872
10873       while(size--) {
10874         if(size) {
10875           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876                 pic16_popGet(AOP(result), offset++)));
10877         } else {
10878           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879                 pic16_popGet(AOP(result), offset++)));
10880         }
10881       }
10882     }
10883
10884 #if 0
10885     /* now some housekeeping stuff */
10886     if (aop) {
10887       /* we had to allocate for this iCode */
10888       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10889       pic16_freeAsmop(NULL,aop,ic,TRUE);
10890     } else { 
10891       /* we did not allocate which means left
10892        * already in a pointer register, then
10893        * if size > 0 && this could be used again
10894        * we have to point it back to where it 
10895        * belongs */
10896       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10897       if (AOP_SIZE(result) > 1
10898         && !OP_SYMBOL(left)->remat
10899         && ( OP_SYMBOL(left)->liveTo > ic->seq
10900             || ic->depth )) {
10901 //        int size = AOP_SIZE(result) - 1;
10902 //        while (size--)
10903 //          pic16_emitcode("dec","%s",rname);
10904         }
10905     }
10906 #endif
10907
10908     /* done */
10909     pic16_freeAsmop(left,NULL,ic,TRUE);
10910     pic16_freeAsmop(result,NULL,ic,TRUE);
10911 }
10912
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left, 
10917                                operand *result, 
10918                                iCode *ic)
10919 {
10920     asmop *aop = NULL;
10921     regs *preg = NULL ;
10922     char *rname ;
10923     sym_link *rtype, *retype;    
10924
10925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10926
10927     rtype = operandType(result);
10928     retype= getSpec(rtype);
10929     
10930     pic16_aopOp(left,ic,FALSE);
10931
10932   /* if the value is already in a pointer register
10933        then don't need anything more */
10934     if (!AOP_INPREG(AOP(left))) {
10935         /* otherwise get a free pointer register */
10936         aop = newAsmop(0);
10937         preg = getFreePtr(ic,&aop,FALSE);
10938         pic16_emitcode("mov","%s,%s",
10939                 preg->name,
10940                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941         rname = preg->name ;
10942     } else
10943         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10944     
10945     pic16_freeAsmop(left,NULL,ic,TRUE);
10946     pic16_aopOp (result,ic,TRUE);
10947
10948     /* if bitfield then unpack the bits */
10949     if (IS_BITFIELD(retype)) 
10950         genUnpackBits (result,left,rname,PPOINTER);
10951     else {
10952         /* we have can just get the values */
10953         int size = AOP_SIZE(result);
10954         int offset = 0 ;        
10955         
10956         while (size--) {
10957             
10958             pic16_emitcode("movx","a,@%s",rname);
10959             pic16_aopPut(AOP(result),"a",offset);
10960             
10961             offset++ ;
10962             
10963             if (size)
10964                 pic16_emitcode("inc","%s",rname);
10965         }
10966     }
10967
10968     /* now some housekeeping stuff */
10969     if (aop) {
10970         /* we had to allocate for this iCode */
10971         pic16_freeAsmop(NULL,aop,ic,TRUE);
10972     } else { 
10973         /* we did not allocate which means left
10974            already in a pointer register, then
10975            if size > 0 && this could be used again
10976            we have to point it back to where it 
10977            belongs */
10978         if (AOP_SIZE(result) > 1 &&
10979             !OP_SYMBOL(left)->remat &&
10980             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10981               ic->depth )) {
10982             int size = AOP_SIZE(result) - 1;
10983             while (size--)
10984                 pic16_emitcode("dec","%s",rname);
10985         }
10986     }
10987
10988     /* done */
10989     pic16_freeAsmop(result,NULL,ic,TRUE);
10990     
10991         
10992 }
10993
10994 #if 0
10995 /* This code is not adjusted to PIC16 and fails utterly.
10996  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10997
10998 /*-----------------------------------------------------------------*/
10999 /* genFarPointerGet - gget value from far space                    */
11000 /*-----------------------------------------------------------------*/
11001 static void genFarPointerGet (operand *left,
11002                               operand *result, iCode *ic)
11003 {
11004     int size, offset ;
11005     sym_link *retype = getSpec(operandType(result));
11006
11007     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11008
11009     pic16_aopOp(left,ic,FALSE);
11010
11011     /* if the operand is already in dptr 
11012     then we do nothing else we move the value to dptr */
11013     if (AOP_TYPE(left) != AOP_STR) {
11014         /* if this is remateriazable */
11015         if (AOP_TYPE(left) == AOP_IMMD)
11016             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11017         else { /* we need to get it byte by byte */
11018             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11019             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11020             if (options.model == MODEL_FLAT24)
11021             {
11022                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11023             }
11024         }
11025     }
11026     /* so dptr know contains the address */
11027     pic16_freeAsmop(left,NULL,ic,TRUE);
11028     pic16_aopOp(result,ic,TRUE);
11029
11030     /* if bit then unpack */
11031     if (IS_BITFIELD(retype)) 
11032         genUnpackBits(result,left,"dptr",FPOINTER);
11033     else {
11034         size = AOP_SIZE(result);
11035         offset = 0 ;
11036
11037         while (size--) {
11038             pic16_emitcode("movx","a,@dptr");
11039             pic16_aopPut(AOP(result),"a",offset++);
11040             if (size)
11041                 pic16_emitcode("inc","dptr");
11042         }
11043     }
11044
11045     pic16_freeAsmop(result,NULL,ic,TRUE);
11046 }
11047 #endif
11048
11049 #if 0
11050 /*-----------------------------------------------------------------*/
11051 /* genCodePointerGet - get value from code space                  */
11052 /*-----------------------------------------------------------------*/
11053 static void genCodePointerGet (operand *left,
11054                                 operand *result, iCode *ic)
11055 {
11056     int size, offset ;
11057     sym_link *retype = getSpec(operandType(result));
11058
11059     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11060
11061     pic16_aopOp(left,ic,FALSE);
11062
11063     /* if the operand is already in dptr 
11064     then we do nothing else we move the value to dptr */
11065     if (AOP_TYPE(left) != AOP_STR) {
11066         /* if this is remateriazable */
11067         if (AOP_TYPE(left) == AOP_IMMD)
11068             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11069         else { /* we need to get it byte by byte */
11070             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11071             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11072             if (options.model == MODEL_FLAT24)
11073             {
11074                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11075             }
11076         }
11077     }
11078     /* so dptr know contains the address */
11079     pic16_freeAsmop(left,NULL,ic,TRUE);
11080     pic16_aopOp(result,ic,FALSE);
11081
11082     /* if bit then unpack */
11083     if (IS_BITFIELD(retype)) 
11084         genUnpackBits(result,left,"dptr",CPOINTER);
11085     else {
11086         size = AOP_SIZE(result);
11087         offset = 0 ;
11088
11089         while (size--) {
11090             pic16_emitcode("clr","a");
11091             pic16_emitcode("movc","a,@a+dptr");
11092             pic16_aopPut(AOP(result),"a",offset++);
11093             if (size)
11094                 pic16_emitcode("inc","dptr");
11095         }
11096     }
11097
11098     pic16_freeAsmop(result,NULL,ic,TRUE);
11099 }
11100 #endif
11101
11102 #if 0
11103 /*-----------------------------------------------------------------*/
11104 /* genGenPointerGet - gget value from generic pointer space        */
11105 /*-----------------------------------------------------------------*/
11106 static void genGenPointerGet (operand *left,
11107                               operand *result, iCode *ic)
11108 {
11109   int size, offset, lit;
11110   sym_link *retype = getSpec(operandType(result));
11111
11112         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11113         pic16_aopOp(left,ic,FALSE);
11114         pic16_aopOp(result,ic,FALSE);
11115         size = AOP_SIZE(result);
11116
11117         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11118
11119         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11120
11121                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11122                 // load FSR0 from immediate
11123                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11124
11125 //              pic16_loadFSR0( left );
11126
11127                 offset = 0;
11128                 while(size--) {
11129                         if(size) {
11130                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11131                         } else {
11132                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11133                         }
11134                         offset++;
11135                 }
11136                 goto release;
11137
11138         }
11139         else { /* we need to get it byte by byte */
11140                 // set up FSR0 with address from left
11141                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11142                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11143                 
11144                 offset = 0 ;
11145
11146                 while(size--) {
11147                         if(size) {
11148                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11149                         } else {
11150                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11151                         }
11152                         offset++;
11153                 }
11154                 goto release;
11155         }
11156
11157   /* if bit then unpack */
11158         if (IS_BITFIELD(retype)) 
11159                 genUnpackBits(result,left,"BAD",GPOINTER);
11160
11161         release:
11162         pic16_freeAsmop(left,NULL,ic,TRUE);
11163         pic16_freeAsmop(result,NULL,ic,TRUE);
11164
11165 }
11166 #endif
11167
11168
11169 /*-----------------------------------------------------------------*/
11170 /* genGenPointerGet - gget value from generic pointer space        */
11171 /*-----------------------------------------------------------------*/
11172 static void genGenPointerGet (operand *left,
11173                               operand *result, iCode *ic)
11174 {
11175   int size, offset, lit;
11176   sym_link *letype = getSpec(operandType(left));
11177
11178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11179     pic16_aopOp(left,ic,FALSE);
11180     pic16_aopOp(result,ic,TRUE);
11181     size = AOP_SIZE(result);
11182
11183     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11184   
11185     /* if bit then unpack */
11186     if (IS_BITFIELD(letype)) {
11187       genUnpackBits(result,left,"BAD",GPOINTER);
11188       goto release;
11189     }
11190
11191     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11192
11193       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11194       // load FSR0 from immediate
11195       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11196
11197       werror(W_POSSBUG2, __FILE__, __LINE__);
11198
11199       offset = 0;
11200       while(size--) {
11201         if(size) {
11202           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11203         } else {
11204           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11205         }
11206         offset++;
11207       }
11208
11209       goto release;
11210
11211     } else { /* we need to get it byte by byte */
11212
11213       /* set up WREG:PRODL:FSR0L with address from left */
11214       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11215       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11216       pic16_mov2w(AOP(left), 2);
11217       pic16_callGenericPointerRW(0, size);
11218       
11219       assignResultValue(result, 1);
11220       
11221       goto release;
11222     }
11223
11224 release:
11225   pic16_freeAsmop(left,NULL,ic,TRUE);
11226   pic16_freeAsmop(result,NULL,ic,TRUE);
11227 }
11228
11229 /*-----------------------------------------------------------------*/
11230 /* genConstPointerGet - get value from const generic pointer space */
11231 /*-----------------------------------------------------------------*/
11232 static void genConstPointerGet (operand *left,
11233                                 operand *result, iCode *ic)
11234 {
11235   //sym_link *retype = getSpec(operandType(result));
11236   // symbol *albl = newiTempLabel(NULL);        // patch 15
11237   // symbol *blbl = newiTempLabel(NULL);        //
11238   // PIC_OPCODE poc;                            // patch 15
11239   int size;
11240   int offset = 0;
11241
11242   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11243   pic16_aopOp(left,ic,FALSE);
11244   pic16_aopOp(result,ic,TRUE);
11245   size = AOP_SIZE(result);
11246
11247   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11248
11249   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11250
11251   // set up table pointer
11252   if( (AOP_TYPE(left) == AOP_PCODE) 
11253       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11254           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11255     {
11256       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11257       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11258       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11259       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11260       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11261       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11262   } else {
11263     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11264     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11265     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11266   }
11267
11268   while(size--) {
11269     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11270     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11271     offset++;
11272   }
11273     
11274   pic16_freeAsmop(left,NULL,ic,TRUE);
11275   pic16_freeAsmop(result,NULL,ic,TRUE);
11276 }
11277
11278
11279 /*-----------------------------------------------------------------*/
11280 /* genPointerGet - generate code for pointer get                   */
11281 /*-----------------------------------------------------------------*/
11282 static void genPointerGet (iCode *ic)
11283 {
11284   operand *left, *result ;
11285   sym_link *type, *etype;
11286   int p_type;
11287
11288     FENTRY;
11289     
11290     left = IC_LEFT(ic);
11291     result = IC_RESULT(ic) ;
11292
11293     /* depending on the type of pointer we need to
11294     move it to the correct pointer register */
11295     type = operandType(left);
11296     etype = getSpec(type);
11297
11298 #if 0
11299     if (IS_PTR_CONST(type))
11300 #else
11301     if (IS_CODEPTR(type))
11302 #endif
11303       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11304
11305     /* if left is of type of pointer then it is simple */
11306     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11307       p_type = DCL_TYPE(type);
11308     else {
11309       /* we have to go by the storage class */
11310       p_type = PTR_TYPE(SPEC_OCLS(etype));
11311
11312       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11313
11314       if (SPEC_OCLS(etype)->codesp ) {
11315         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11316         //p_type = CPOINTER ;   
11317       } else
11318       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11319         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11320         /*p_type = FPOINTER ;*/ 
11321       } else
11322       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11323         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11324         /* p_type = PPOINTER; */
11325       } else
11326       if (SPEC_OCLS(etype) == idata ) {
11327         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11328         /* p_type = IPOINTER; */
11329       } else {
11330         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11331         /* p_type = POINTER ; */
11332       }
11333     }
11334
11335     /* now that we have the pointer type we assign
11336     the pointer values */
11337     switch (p_type) {
11338       case POINTER:     
11339       case FPOINTER:
11340       case IPOINTER:
11341         genNearPointerGet (left,result,ic);
11342         break;
11343
11344       case PPOINTER:
11345         genPagedPointerGet(left,result,ic);
11346         break;
11347
11348 #if 0
11349       /* PICs do not support FAR pointers... */
11350       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11351       case FPOINTER:
11352         genFarPointerGet (left,result,ic);
11353         break;
11354 #endif
11355
11356       case CPOINTER:
11357         genConstPointerGet (left,result,ic);
11358         //pic16_emitcodePointerGet (left,result,ic);
11359         break;
11360
11361       case GPOINTER:
11362 #if 0
11363       if (IS_PTR_CONST(type))
11364         genConstPointerGet (left,result,ic);
11365       else
11366 #endif
11367         genGenPointerGet (left,result,ic);
11368       break;
11369
11370     default:
11371       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11372               "genPointerGet: illegal pointer type");
11373     
11374     }
11375 }
11376
11377 /*-----------------------------------------------------------------*/
11378 /* genPackBits - generates code for packed bit storage             */
11379 /*-----------------------------------------------------------------*/
11380 static void genPackBits (sym_link    *etype , operand *result,
11381                          operand *right ,
11382                          char *rname, int p_type)
11383 {
11384   int shCnt = 0 ;
11385   int offset = 0  ;
11386   int rLen = 0 ;
11387   int blen, bstr ;   
11388   int shifted_and_masked = 0;
11389   unsigned long lit = (unsigned long)-1;
11390   sym_link *retype;
11391
11392   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11393   blen = SPEC_BLEN(etype);
11394   bstr = SPEC_BSTR(etype);
11395
11396   retype = getSpec(operandType(right));
11397
11398   if(AOP_TYPE(right) == AOP_LIT) {
11399     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11400     
11401     if((blen == 1) && (bstr < 8)) {
11402       /* it is a single bit, so use the appropriate bit instructions */
11403
11404       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11405
11406       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11407         /* workaround to reduce the extra lfsr instruction */
11408         if(lit) {
11409           pic16_emitpcode(POC_BSF,
11410               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11411         } else {
11412           pic16_emitpcode(POC_BCF,
11413               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11414         }
11415       } else {
11416         if (PIC_IS_DATA_PTR(operandType(result))) {
11417           pic16_loadFSR0(result, 0);
11418           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11419               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11420         } else {
11421           /* get old value */
11422           pic16_derefPtr (result, p_type, 0, NULL);
11423           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11424               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11425           /* write back new value */
11426           pic16_derefPtr (result, p_type, 1, NULL);
11427         }
11428       }
11429
11430       return;
11431     }
11432     /* IORLW below is more efficient */
11433     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11434     lit = (lit & ((1UL << blen) - 1)) << bstr;
11435     shifted_and_masked = 1;
11436     offset++;
11437   } else
11438     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11439         && IS_BITFIELD(retype) 
11440         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11441         && (blen == 1)) {
11442       int rblen, rbstr;
11443
11444       rblen = SPEC_BLEN( retype );
11445       rbstr = SPEC_BSTR( retype );
11446
11447       if(IS_BITFIELD(etype)) {
11448         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11449         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11450       } else {
11451         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11452       }
11453
11454       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11455
11456       if(IS_BITFIELD(etype)) {
11457         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11458       } else {
11459         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11460       }
11461
11462       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11463
11464       return;
11465     } else {
11466       /* move right to W */
11467       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11468     }
11469
11470   /* if the bit length is less than or   */
11471   /* it exactly fits a byte then         */
11472   if((shCnt=SPEC_BSTR(etype))
11473       || SPEC_BLEN(etype) <= 8 )  {
11474     int fsr0_setup = 0;
11475
11476     if (blen != 8 || bstr != 0) {
11477       // we need to combine the value with the old value
11478       if(!shifted_and_masked)
11479       {
11480         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11481
11482         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11483             SPEC_BSTR(etype), SPEC_BLEN(etype));
11484
11485         /* shift left acc, do NOT mask the result again */
11486         AccLsh(shCnt, 0);
11487
11488         /* using PRODH as a temporary register here */
11489         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11490       }
11491
11492       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11493         || IS_DIRECT(result)) {
11494         /* access symbol directly */
11495         pic16_mov2w (AOP(result), 0);
11496       } else {
11497         /* get old value */
11498         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11499       }
11500 #if 1
11501       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11502             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11503                             (unsigned char)(0xff >> (8-bstr))) ));
11504       if (!shifted_and_masked) {
11505         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11506       } else {
11507         /* We have the shifted and masked (literal) right value in `lit' */
11508         if (lit != 0)
11509           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11510       }
11511     } // if (blen != 8 || bstr != 0)
11512
11513     /* write new value back */
11514     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11515         || IS_DIRECT(result)) {
11516       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11517     } else {
11518       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11519     }
11520 #endif
11521
11522     return;
11523   }
11524
11525
11526 #if 0
11527   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11528   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11529   exit(-1);
11530 #endif
11531
11532
11533   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11534   rLen = SPEC_BLEN(etype)-8;
11535
11536   /* now generate for lengths greater than one byte */
11537   while (1) {
11538     rLen -= 8 ;
11539     if (rLen <= 0 ) {
11540       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11541       break ;
11542     }
11543
11544     switch (p_type) {
11545       case POINTER:
11546         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11547         break;
11548
11549         /*
11550            case FPOINTER:
11551            MOVA(l);
11552            pic16_emitcode("movx","@dptr,a");
11553            break;
11554
11555            case GPOINTER:
11556            MOVA(l);
11557            DEBUGpic16_emitcode(";lcall","__gptrput");
11558            break;  
11559          */
11560       default:
11561         assert(0);
11562     }   
11563
11564
11565     pic16_mov2w(AOP(right), offset++);
11566   }
11567
11568   /* last last was not complete */
11569   if (rLen)   {
11570     /* save the byte & read byte */
11571     switch (p_type) {
11572       case POINTER:
11573         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11574         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11575         break;
11576
11577         /*
11578            case FPOINTER:
11579            pic16_emitcode ("mov","b,a");
11580            pic16_emitcode("movx","a,@dptr");
11581            break;
11582
11583            case GPOINTER:
11584            pic16_emitcode ("push","b");
11585            pic16_emitcode ("push","acc");
11586            pic16_emitcode ("lcall","__gptrget");
11587            pic16_emitcode ("pop","b");
11588            break;
11589          */
11590       default:
11591         assert(0);
11592     }
11593     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11594     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11595     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11596     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11597     //        pic16_emitcode ("orl","a,b");
11598   }
11599
11600   //    if (p_type == GPOINTER)
11601   //        pic16_emitcode("pop","b");
11602
11603   switch (p_type) {
11604
11605     case POINTER:
11606       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11607       //        pic16_emitcode("mov","@%s,a",rname);
11608       break;
11609       /*
11610          case FPOINTER:
11611          pic16_emitcode("movx","@dptr,a");
11612          break;
11613
11614          case GPOINTER:
11615          DEBUGpic16_emitcode(";lcall","__gptrput");
11616          break;                 
11617        */
11618     default:
11619       assert(0);
11620   }
11621
11622   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11623 }
11624
11625 /*-----------------------------------------------------------------*/
11626 /* genDataPointerSet - remat pointer to data space                 */
11627 /*-----------------------------------------------------------------*/
11628 static void genDataPointerSet(operand *right,
11629                               operand *result,
11630                               iCode *ic)
11631 {
11632   int size, offset = 0, resoffset=0 ;
11633
11634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11635     pic16_aopOp(right,ic,FALSE);
11636
11637     size = AOP_SIZE(right);
11638
11639 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11640
11641 #if 0
11642     if ( AOP_TYPE(result) == AOP_PCODE) {
11643       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11644               AOP(result)->aopu.pcop->name,
11645                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11646               PCOR(AOP(result)->aopu.pcop)->instance:
11647               PCOI(AOP(result)->aopu.pcop)->offset);
11648     }
11649 #endif
11650
11651     if(AOP(result)->aopu.pcop->type == PO_DIR)
11652       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11653
11654     while (size--) {
11655       if (AOP_TYPE(right) == AOP_LIT) {
11656         unsigned int lit;
11657
11658           if(!IS_FLOAT(operandType( right )))
11659             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11660           else {
11661             union {
11662               unsigned long lit_int;
11663               float lit_float;
11664             } info;
11665         
11666               /* take care if literal is a float */
11667               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11668               lit = info.lit_int;
11669           }
11670                     lit = lit >> (8*offset);
11671                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11672                 } else {
11673                   pic16_mov2w(AOP(right), offset);
11674                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11675                 }
11676                 offset++;
11677                 resoffset++;
11678         }
11679
11680     pic16_freeAsmop(right,NULL,ic,TRUE);
11681 }
11682
11683
11684
11685 /*-----------------------------------------------------------------*/
11686 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11687 /*-----------------------------------------------------------------*/
11688 static void genNearPointerSet (operand *right,
11689                                operand *result, 
11690                                iCode *ic)
11691 {
11692   asmop *aop = NULL;
11693   sym_link *retype;
11694   sym_link *ptype = operandType(result);
11695   sym_link *resetype;
11696     
11697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11698     retype= getSpec(operandType(right));
11699     resetype = getSpec(operandType(result));
11700   
11701     pic16_aopOp(result,ic,FALSE);
11702     
11703     /* if the result is rematerializable &
11704      * in data space & not a bit variable */
11705         
11706     /* and result is not a bit variable */
11707     if (AOP_TYPE(result) == AOP_PCODE
11708 //      && AOP_TYPE(result) == AOP_IMMD
11709       && DCL_TYPE(ptype) == POINTER
11710       && !IS_BITFIELD(retype)
11711       && !IS_BITFIELD(resetype)) {
11712
11713         genDataPointerSet (right,result,ic);
11714         pic16_freeAsmop(result,NULL,ic,TRUE);
11715       return;
11716     }
11717
11718     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11719     pic16_aopOp(right,ic,FALSE);
11720     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11721
11722     /* if bitfield then unpack the bits */
11723     if (IS_BITFIELD(resetype)) {
11724       genPackBits (resetype, result, right, NULL, POINTER);
11725     } else {
11726       /* we have can just get the values */
11727       int size = AOP_SIZE(right);
11728       int offset = 0 ;    
11729
11730         pic16_loadFSR0(result, 0);
11731             
11732         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11733         while (size--) {
11734           if (AOP_TYPE(right) == AOP_LIT) {
11735             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11736             if (size) {
11737               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11738             } else {
11739               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11740             }
11741           } else { // no literal
11742             if(size) {
11743               pic16_emitpcode(POC_MOVFF,
11744                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11745                   pic16_popCopyReg(&pic16_pc_postinc0)));
11746             } else {
11747               pic16_emitpcode(POC_MOVFF,
11748                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11749                   pic16_popCopyReg(&pic16_pc_indf0)));
11750             }
11751           }
11752           
11753           offset++;
11754         }
11755     }
11756
11757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11758     /* now some housekeeping stuff */
11759     if (aop) {
11760       /* we had to allocate for this iCode */
11761       pic16_freeAsmop(NULL,aop,ic,TRUE);
11762     } else { 
11763       /* we did not allocate which means left
11764        * already in a pointer register, then
11765        * if size > 0 && this could be used again
11766        * we have to point it back to where it 
11767        * belongs */
11768       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11769       if (AOP_SIZE(right) > 1
11770         && !OP_SYMBOL(result)->remat
11771         && ( OP_SYMBOL(result)->liveTo > ic->seq
11772         || ic->depth )) {
11773
11774           int size = AOP_SIZE(right) - 1;
11775
11776             while (size--)
11777               pic16_emitcode("decf","fsr0,f");
11778               //pic16_emitcode("dec","%s",rname);
11779       }
11780     }
11781
11782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11783     /* done */
11784 //release:
11785     pic16_freeAsmop(right,NULL,ic,TRUE);
11786     pic16_freeAsmop(result,NULL,ic,TRUE);
11787 }
11788
11789 /*-----------------------------------------------------------------*/
11790 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11791 /*-----------------------------------------------------------------*/
11792 static void genPagedPointerSet (operand *right,
11793                                operand *result, 
11794                                iCode *ic)
11795 {
11796     asmop *aop = NULL;
11797     regs *preg = NULL ;
11798     char *rname , *l;
11799     sym_link *retype;
11800        
11801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11802
11803     retype= getSpec(operandType(right));
11804     
11805     pic16_aopOp(result,ic,FALSE);
11806     
11807     /* if the value is already in a pointer register
11808        then don't need anything more */
11809     if (!AOP_INPREG(AOP(result))) {
11810         /* otherwise get a free pointer register */
11811         aop = newAsmop(0);
11812         preg = getFreePtr(ic,&aop,FALSE);
11813         pic16_emitcode("mov","%s,%s",
11814                 preg->name,
11815                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11816         rname = preg->name ;
11817     } else
11818         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11819     
11820     pic16_freeAsmop(result,NULL,ic,TRUE);
11821     pic16_aopOp (right,ic,FALSE);
11822
11823     /* if bitfield then unpack the bits */
11824     if (IS_BITFIELD(retype)) 
11825         genPackBits (retype,result,right,rname,PPOINTER);
11826     else {
11827         /* we have can just get the values */
11828         int size = AOP_SIZE(right);
11829         int offset = 0 ;        
11830         
11831         while (size--) {
11832             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11833             
11834             MOVA(l);
11835             pic16_emitcode("movx","@%s,a",rname);
11836
11837             if (size)
11838                 pic16_emitcode("inc","%s",rname);
11839
11840             offset++;
11841         }
11842     }
11843     
11844     /* now some housekeeping stuff */
11845     if (aop) {
11846         /* we had to allocate for this iCode */
11847         pic16_freeAsmop(NULL,aop,ic,TRUE);
11848     } else { 
11849         /* we did not allocate which means left
11850            already in a pointer register, then
11851            if size > 0 && this could be used again
11852            we have to point it back to where it 
11853            belongs */
11854         if (AOP_SIZE(right) > 1 &&
11855             !OP_SYMBOL(result)->remat &&
11856             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11857               ic->depth )) {
11858             int size = AOP_SIZE(right) - 1;
11859             while (size--)
11860                 pic16_emitcode("dec","%s",rname);
11861         }
11862     }
11863
11864     /* done */
11865     pic16_freeAsmop(right,NULL,ic,TRUE);
11866     
11867         
11868 }
11869
11870 #if 0
11871 /* This code is not adjusted to PIC16 and fails utterly...
11872  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11873
11874 /*-----------------------------------------------------------------*/
11875 /* genFarPointerSet - set value from far space                     */
11876 /*-----------------------------------------------------------------*/
11877 static void genFarPointerSet (operand *right,
11878                               operand *result, iCode *ic)
11879 {
11880     int size, offset ;
11881     sym_link *retype = getSpec(operandType(right));
11882
11883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11884     pic16_aopOp(result,ic,FALSE);
11885
11886     /* if the operand is already in dptr 
11887     then we do nothing else we move the value to dptr */
11888     if (AOP_TYPE(result) != AOP_STR) {
11889         /* if this is remateriazable */
11890         if (AOP_TYPE(result) == AOP_IMMD)
11891             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11892         else { /* we need to get it byte by byte */
11893             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11894             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11895             if (options.model == MODEL_FLAT24)
11896             {
11897                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11898             }
11899         }
11900     }
11901     /* so dptr know contains the address */
11902     pic16_freeAsmop(result,NULL,ic,TRUE);
11903     pic16_aopOp(right,ic,FALSE);
11904
11905     /* if bit then unpack */
11906     if (IS_BITFIELD(retype)) 
11907         genPackBits(retype,result,right,"dptr",FPOINTER);
11908     else {
11909         size = AOP_SIZE(right);
11910         offset = 0 ;
11911
11912         while (size--) {
11913             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11914             MOVA(l);
11915             pic16_emitcode("movx","@dptr,a");
11916             if (size)
11917                 pic16_emitcode("inc","dptr");
11918         }
11919     }
11920
11921     pic16_freeAsmop(right,NULL,ic,TRUE);
11922 }
11923 #endif
11924
11925 /*-----------------------------------------------------------------*/
11926 /* genGenPointerSet - set value from generic pointer space         */
11927 /*-----------------------------------------------------------------*/
11928 #if 0
11929 static void genGenPointerSet (operand *right,
11930                               operand *result, iCode *ic)
11931 {
11932         int i, size, offset, lit;
11933         sym_link *retype = getSpec(operandType(right));
11934
11935         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11936
11937         pic16_aopOp(result,ic,FALSE);
11938         pic16_aopOp(right,ic,FALSE);
11939         size = AOP_SIZE(right);
11940         offset = 0;
11941
11942         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11943
11944         /* if the operand is already in dptr 
11945                 then we do nothing else we move the value to dptr */
11946         if (AOP_TYPE(result) != AOP_STR) {
11947                 /* if this is remateriazable */
11948                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11949                 // WARNING: anythig until "else" is untested!
11950                 if (AOP_TYPE(result) == AOP_IMMD) {
11951                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11952                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11953                         // load FSR0 from immediate
11954                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11955                         offset = 0;
11956                         while(size--) {
11957                                 if(size) {
11958                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11959                                 } else {
11960                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11961                                 }
11962                                 offset++;
11963                         }
11964                         goto release;
11965                 }
11966                 else { /* we need to get it byte by byte */
11967                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11968                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11969
11970                         // set up FSR0 with address of result
11971                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11972                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11973
11974                         /* hack hack! see if this the FSR. If so don't load W */
11975                         if(AOP_TYPE(right) != AOP_ACC) {
11976
11977                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11978
11979                                 if(AOP_TYPE(right) == AOP_LIT)
11980                                 {
11981                                         // copy literal
11982                                         // note: pic16_popGet handles sign extension
11983                                         for(i=0;i<size;i++) {
11984                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11985                                                 if(i < size-1)
11986                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11987                                                 else
11988                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11989                                         }
11990                                 } else {
11991                                         // copy regs
11992
11993                                         for(i=0;i<size;i++) {
11994                                                 if(i < size-1)
11995                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11996                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11997                                                 else
11998                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11999                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12000                                         }
12001                                 }
12002                                 goto release;
12003                         } 
12004                         // right = ACC
12005                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12006                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12007                         goto release;
12008         } // if (AOP_TYPE(result) != AOP_IMMD)
12009
12010         } // if (AOP_TYPE(result) != AOP_STR)
12011         /* so dptr know contains the address */
12012
12013
12014         /* if bit then unpack */
12015         if (IS_BITFIELD(retype)) 
12016                 genPackBits(retype,result,right,"dptr",GPOINTER);
12017         else {
12018                 size = AOP_SIZE(right);
12019                 offset = 0 ;
12020
12021                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12022
12023                 // set up FSR0 with address of result
12024                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12025                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12026         
12027                 while (size--) {
12028                         if (AOP_TYPE(right) == AOP_LIT) {
12029                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12030                                 if (size) {
12031                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12032                                 } else {
12033                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12034                                 }
12035                         } else { // no literal
12036                                 if(size) {
12037                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12038                                 } else {
12039                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12040                                 }
12041                         }
12042                         offset++;
12043                 }
12044         }
12045
12046         release:
12047         pic16_freeAsmop(right,NULL,ic,TRUE);
12048         pic16_freeAsmop(result,NULL,ic,TRUE);
12049 }
12050 #endif
12051
12052 static void genGenPointerSet (operand *right,
12053                               operand *result, iCode *ic)
12054 {
12055   int size;
12056   sym_link *retype = getSpec(operandType(result));
12057
12058     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12059
12060     pic16_aopOp(result,ic,FALSE);
12061     pic16_aopOp(right,ic,FALSE);
12062     size = AOP_SIZE(right);
12063
12064     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12065
12066
12067     /* if bit then unpack */
12068     if (IS_BITFIELD(retype)) {
12069 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12070       genPackBits(retype,result,right,"dptr",GPOINTER);
12071       goto release;
12072     }
12073
12074     size = AOP_SIZE(right);
12075
12076     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12077
12078
12079     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12080
12081     /* value of right+0 is placed on stack, which will be retrieved
12082      * by the support function thus restoring the stack. The important
12083      * thing is that there is no need to manually restore stack pointer
12084      * here */
12085     pushaop(AOP(right), 0);
12086 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12087     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12088     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12089     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12090     
12091     /* load address to write to in WREG:FSR0H:FSR0L */
12092     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12093                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12094     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12095                                 pic16_popCopyReg(&pic16_pc_prodl)));
12096     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12097     
12098     pic16_callGenericPointerRW(1, size);
12099
12100 release:
12101     pic16_freeAsmop(right,NULL,ic,TRUE);
12102     pic16_freeAsmop(result,NULL,ic,TRUE);
12103 }
12104
12105 /*-----------------------------------------------------------------*/
12106 /* genPointerSet - stores the value into a pointer location        */
12107 /*-----------------------------------------------------------------*/
12108 static void genPointerSet (iCode *ic)
12109 {    
12110   operand *right, *result ;
12111   sym_link *type, *etype;
12112   int p_type;
12113
12114     FENTRY;
12115
12116     right = IC_RIGHT(ic);
12117     result = IC_RESULT(ic) ;
12118
12119     /* depending on the type of pointer we need to
12120     move it to the correct pointer register */
12121     type = operandType(result);
12122     etype = getSpec(type);
12123     
12124     /* if left is of type of pointer then it is simple */
12125     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12126         p_type = DCL_TYPE(type);
12127     }
12128     else {
12129         /* we have to go by the storage class */
12130         p_type = PTR_TYPE(SPEC_OCLS(etype));
12131
12132 /*      if (SPEC_OCLS(etype)->codesp ) { */
12133 /*          p_type = CPOINTER ;  */
12134 /*      } */
12135 /*      else */
12136 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12137 /*              p_type = FPOINTER ; */
12138 /*          else */
12139 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12140 /*                  p_type = PPOINTER ; */
12141 /*              else */
12142 /*                  if (SPEC_OCLS(etype) == idata ) */
12143 /*                      p_type = IPOINTER ; */
12144 /*                  else */
12145 /*                      p_type = POINTER ; */
12146     }
12147
12148     /* now that we have the pointer type we assign
12149     the pointer values */
12150     switch (p_type) {
12151       case POINTER:
12152       case FPOINTER:
12153       case IPOINTER:
12154         genNearPointerSet (right,result,ic);
12155         break;
12156
12157       case PPOINTER:
12158         genPagedPointerSet (right,result,ic);
12159         break;
12160
12161 #if 0
12162       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12163       case FPOINTER:
12164         genFarPointerSet (right,result,ic);
12165         break;
12166 #endif
12167         
12168       case GPOINTER:
12169         genGenPointerSet (right,result,ic);
12170         break;
12171
12172       default:
12173         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12174           "genPointerSet: illegal pointer type");
12175     }
12176 }
12177
12178 /*-----------------------------------------------------------------*/
12179 /* genIfx - generate code for Ifx statement                        */
12180 /*-----------------------------------------------------------------*/
12181 static void genIfx (iCode *ic, iCode *popIc)
12182 {
12183   operand *cond = IC_COND(ic);
12184   int isbit =0;
12185
12186     FENTRY;
12187
12188     pic16_aopOp(cond,ic,FALSE);
12189
12190     /* get the value into acc */
12191     if (AOP_TYPE(cond) != AOP_CRY)
12192       pic16_toBoolean(cond);
12193     else
12194       isbit = 1;
12195     /* the result is now in the accumulator */
12196     pic16_freeAsmop(cond,NULL,ic,TRUE);
12197
12198     /* if there was something to be popped then do it */
12199     if (popIc)
12200       genIpop(popIc);
12201
12202     /* if the condition is  a bit variable */
12203     if (isbit && IS_ITEMP(cond) && 
12204         SPIL_LOC(cond)) {
12205       genIfxJump(ic,"c");
12206       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12207     } else {
12208       if (isbit && !IS_ITEMP(cond))
12209         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12210         else
12211         genIfxJump(ic,"a");
12212     }
12213     ic->generated = 1;
12214 }
12215
12216 /*-----------------------------------------------------------------*/
12217 /* genAddrOf - generates code for address of                       */
12218 /*-----------------------------------------------------------------*/
12219 static void genAddrOf (iCode *ic)
12220 {
12221   operand *result, *left;
12222   int size;
12223   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12224   pCodeOp *pcop0, *pcop1, *pcop2;
12225
12226     FENTRY;
12227
12228     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12229
12230     sym = OP_SYMBOL( IC_LEFT(ic) );
12231     
12232     if(sym->onStack) {
12233       /* get address of symbol on stack */
12234       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12235 #if 0
12236       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12237                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12238 #endif
12239
12240       // operands on stack are accessible via "FSR2 + index" with index
12241       // starting at 2 for arguments and growing from 0 downwards for
12242       // local variables (index == 0 is not assigned so we add one here)
12243       {
12244         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12245
12246           if (soffs <= 0) {
12247             assert (soffs < 0);
12248             soffs++;
12249           } // if
12250
12251           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12252           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12253           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12254           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12255           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12256           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12257           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12258       }
12259
12260       goto release;
12261     }
12262         
12263 //      if(pic16_debug_verbose) {
12264 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12265 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12266 //      }
12267         
12268     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12269     size = AOP_SIZE(IC_RESULT(ic));
12270
12271     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12272     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12273     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12274         
12275     if (size == 3) {
12276       pic16_emitpcode(POC_MOVLW, pcop0);
12277       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12278       pic16_emitpcode(POC_MOVLW, pcop1);
12279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12280       pic16_emitpcode(POC_MOVLW, pcop2);
12281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12282     } else
12283     if (size == 2) {
12284       pic16_emitpcode(POC_MOVLW, pcop0);
12285       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12286       pic16_emitpcode(POC_MOVLW, pcop1);
12287     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12288     } else {
12289       pic16_emitpcode(POC_MOVLW, pcop0);
12290       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12291     }
12292
12293     pic16_freeAsmop(left, NULL, ic, FALSE);
12294 release:
12295     pic16_freeAsmop(result,NULL,ic,TRUE);
12296 }
12297
12298
12299 #if 0
12300 /*-----------------------------------------------------------------*/
12301 /* genFarFarAssign - assignment when both are in far space         */
12302 /*-----------------------------------------------------------------*/
12303 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12304 {
12305     int size = AOP_SIZE(right);
12306     int offset = 0;
12307     char *l ;
12308     /* first push the right side on to the stack */
12309     while (size--) {
12310         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12311         MOVA(l);
12312         pic16_emitcode ("push","acc");
12313     }
12314     
12315     pic16_freeAsmop(right,NULL,ic,FALSE);
12316     /* now assign DPTR to result */
12317     pic16_aopOp(result,ic,FALSE);
12318     size = AOP_SIZE(result);
12319     while (size--) {
12320         pic16_emitcode ("pop","acc");
12321         pic16_aopPut(AOP(result),"a",--offset);
12322     }
12323     pic16_freeAsmop(result,NULL,ic,FALSE);
12324         
12325 }
12326 #endif
12327
12328 /*-----------------------------------------------------------------*/
12329 /* genAssign - generate code for assignment                        */
12330 /*-----------------------------------------------------------------*/
12331 static void genAssign (iCode *ic)
12332 {
12333   operand *result, *right;
12334   sym_link *restype, *rtype;
12335   int size, offset,know_W;
12336   unsigned long lit = 0L;
12337
12338     result = IC_RESULT(ic);
12339     right  = IC_RIGHT(ic) ;
12340
12341     FENTRY;
12342   
12343     /* if they are the same */
12344     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12345       return ;
12346
12347     /* reversed order operands are aopOp'ed so that result operand
12348      * is effective in case right is a stack symbol. This maneauver
12349      * allows to use the _G.resDirect flag later */
12350      pic16_aopOp(result,ic,TRUE);
12351     pic16_aopOp(right,ic,FALSE);
12352
12353     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12354
12355     /* if they are the same registers */
12356     if (pic16_sameRegs(AOP(right),AOP(result)))
12357       goto release;
12358
12359     /* if the result is a bit */
12360     if (AOP_TYPE(result) == AOP_CRY) {
12361       /* if the right size is a literal then
12362          we know what the value is */
12363       if (AOP_TYPE(right) == AOP_LIT) {
12364           
12365         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12366             pic16_popGet(AOP(result),0));
12367
12368         if (((int) operandLitValue(right))) 
12369           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12370               AOP(result)->aopu.aop_dir,
12371               AOP(result)->aopu.aop_dir);
12372         else
12373           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12374               AOP(result)->aopu.aop_dir,
12375               AOP(result)->aopu.aop_dir);
12376         
12377         goto release;
12378       }
12379
12380       /* the right is also a bit variable */
12381       if (AOP_TYPE(right) == AOP_CRY) {
12382         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12383         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12384         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12385
12386         goto release ;
12387       }
12388
12389       /* we need to or */
12390       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12391       pic16_toBoolean(right);
12392       emitSKPZ;
12393       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12394       //pic16_aopPut(AOP(result),"a",0);
12395       goto release ;
12396     }
12397
12398     /* bit variables done */
12399     /* general case */
12400     size = AOP_SIZE(result);
12401     offset = 0 ;
12402
12403   /* bit variables done */
12404   /* general case */
12405   size = AOP_SIZE(result);
12406   restype = operandType(result);
12407   rtype = operandType(right);
12408   offset = 0 ;
12409
12410   if(AOP_TYPE(right) == AOP_LIT) {
12411     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12412     {
12413       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12414
12415       /* patch tag for literals that are cast to pointers */
12416       if (IS_CODEPTR(restype)) {
12417         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12418         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12419       } else {
12420         if (IS_GENPTR(restype))
12421         {
12422           if (IS_CODEPTR(rtype)) {
12423             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12424             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12425           } else if (PIC_IS_DATA_PTR(rtype)) {
12426             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12427             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12428           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12429             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12430           } else if (IS_PTR(rtype)) {
12431             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12432             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12433           }
12434         }
12435       }
12436     } else {
12437       union {
12438         unsigned long lit_int;
12439         float lit_float;
12440       } info;
12441
12442
12443       if(IS_FIXED16X16(operandType(right))) {
12444         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12445       } else {
12446         /* take care if literal is a float */
12447         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12448         lit = info.lit_int;
12449       }
12450     }
12451   }
12452
12453 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12454 //                      sizeof(unsigned long int), sizeof(float));
12455
12456
12457     if (AOP_TYPE(right) == AOP_REG) {
12458       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12459       while (size--) {
12460         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12461       } // while
12462       goto release;
12463     }
12464
12465     /* when do we have to read the program memory?
12466      * - if right itself is a symbol in code space
12467      *   (we don't care what it points to if it's a pointer)
12468      * - AND right is not a function (we would want its address)
12469      */
12470     if(AOP_TYPE(right) != AOP_LIT
12471       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12472       && !IS_FUNC(OP_SYM_TYPE(right))
12473       && !IS_ITEMP(right)) {
12474
12475       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12476       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12477       
12478       // set up table pointer
12479       if(is_LitOp(right)) {
12480 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12481         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12482         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12483         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12484         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12485         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12486         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12487       } else {
12488 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12489         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12490             pic16_popCopyReg(&pic16_pc_tblptrl)));
12491         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12492             pic16_popCopyReg(&pic16_pc_tblptrh)));
12493         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12494             pic16_popCopyReg(&pic16_pc_tblptru)));
12495       }
12496
12497       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12498       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12499       while(size--) {
12500         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12501         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12502             pic16_popGet(AOP(result),offset)));
12503         offset++;
12504       }
12505
12506       /* FIXME: for pointers we need to extend differently (according
12507        * to pointer type DATA/CODE/EEPROM/... :*/
12508       size = getSize(OP_SYM_TYPE(right));
12509       if(AOP_SIZE(result) > size) {
12510         size = AOP_SIZE(result) - size;
12511         while(size--) {
12512           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12513           offset++;
12514         }
12515       }
12516       goto release;
12517     }
12518
12519 #if 0
12520     /* VR - What is this?! */
12521     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12522       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12523       
12524       if(aopIdx(AOP(result),0) == 4) {
12525         /* this is a workaround to save value of right into wreg too,
12526          * value of wreg is going to be used later */
12527         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12528         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12529         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12530         goto release;
12531       } else
12532 //      assert(0);
12533       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12534     }
12535 #endif
12536
12537   know_W=-1;
12538   while (size--) {
12539     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12540     if(AOP_TYPE(right) == AOP_LIT) {
12541       if(lit&0xff) {
12542         if(know_W != (lit&0xff))
12543           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12544         know_W = lit&0xff;
12545         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12546       } else
12547         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12548
12549       lit >>= 8;
12550
12551     } else if (AOP_TYPE(right) == AOP_CRY) {
12552       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12553       if(offset == 0) {
12554         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12555         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12556         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12557       }
12558     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12559         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12560         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12561     } else {
12562       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12563
12564       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12565           if(AOP_TYPE(result) == AOP_ACC) {
12566             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12567           } else
12568           if(AOP_TYPE(right) == AOP_ACC) {
12569             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12570           } else {
12571             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12572           }
12573       }
12574     }
12575       
12576       offset++;
12577     }
12578   
12579 release:
12580   pic16_freeAsmop (right,NULL,ic,FALSE);
12581   pic16_freeAsmop (result,NULL,ic,TRUE);
12582
12583
12584 /*-----------------------------------------------------------------*/
12585 /* genJumpTab - generates code for jump table                       */
12586 /*-----------------------------------------------------------------*/
12587 static void genJumpTab (iCode *ic)
12588 {
12589   symbol *jtab;
12590   char *l;
12591   pCodeOp *jt_offs;
12592   pCodeOp *jt_offs_hi;
12593   pCodeOp *jt_label;
12594
12595     FENTRY;
12596
12597     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12598     /* get the condition into accumulator */
12599     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12600     MOVA(l);
12601     /* multiply by three */
12602     pic16_emitcode("add","a,acc");
12603     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12604
12605     jtab = newiTempLabel(NULL);
12606     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12607     pic16_emitcode("jmp","@a+dptr");
12608     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12609
12610 #if 0
12611     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12612     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12613     emitSKPNC;
12614     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12615     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12616     pic16_emitpLabel(jtab->key);
12617
12618 #else
12619
12620     jt_offs = pic16_popGetTempReg(0);
12621     jt_offs_hi = pic16_popGetTempReg(1);
12622     jt_label = pic16_popGetLabel (jtab->key);
12623     //fprintf (stderr, "Creating jump table...\n");
12624
12625     // calculate offset into jump table (idx * sizeof (GOTO))
12626     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12627     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12628     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12629     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12630     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12631     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12632     pic16_emitpcode(POC_MOVWF , jt_offs);
12633
12634     // prepare PCLATx (set to first entry in jump table)
12635     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12636     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12637     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12638     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12639     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12640
12641     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12642     pic16_emitpcode(POC_ADDWF , jt_offs);
12643     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12644     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12645     emitSKPNC;
12646     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12647
12648     // release temporaries and prepare jump into table (new PCL --> WREG)
12649     pic16_emitpcode(POC_MOVFW , jt_offs);
12650     pic16_popReleaseTempReg (jt_offs_hi, 1);
12651     pic16_popReleaseTempReg (jt_offs, 0);
12652
12653     // jump into the table
12654     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12655
12656     pic16_emitpLabelFORCE(jtab->key);
12657 #endif
12658
12659     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12660 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12661
12662     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12663     /* now generate the jump labels */
12664     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12665          jtab = setNextItem(IC_JTLABELS(ic))) {
12666 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12667         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12668         
12669     }
12670     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12671
12672 }
12673
12674 /*-----------------------------------------------------------------*/
12675 /* genMixedOperation - gen code for operators between mixed types  */
12676 /*-----------------------------------------------------------------*/
12677 /*
12678   TSD - Written for the PIC port - but this unfortunately is buggy.
12679   This routine is good in that it is able to efficiently promote 
12680   types to different (larger) sizes. Unfortunately, the temporary
12681   variables that are optimized out by this routine are sometimes
12682   used in other places. So until I know how to really parse the 
12683   iCode tree, I'm going to not be using this routine :(.
12684 */
12685 static int genMixedOperation (iCode *ic)
12686 {
12687 #if 0
12688   operand *result = IC_RESULT(ic);
12689   sym_link *ctype = operandType(IC_LEFT(ic));
12690   operand *right = IC_RIGHT(ic);
12691   int ret = 0;
12692   int big,small;
12693   int offset;
12694
12695   iCode *nextic;
12696   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12697
12698   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12699
12700   nextic = ic->next;
12701   if(!nextic)
12702     return 0;
12703
12704   nextright = IC_RIGHT(nextic);
12705   nextleft  = IC_LEFT(nextic);
12706   nextresult = IC_RESULT(nextic);
12707
12708   pic16_aopOp(right,ic,FALSE);
12709   pic16_aopOp(result,ic,FALSE);
12710   pic16_aopOp(nextright,  nextic, FALSE);
12711   pic16_aopOp(nextleft,   nextic, FALSE);
12712   pic16_aopOp(nextresult, nextic, FALSE);
12713
12714   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12715
12716     operand *t = right;
12717     right = nextright;
12718     nextright = t; 
12719
12720     pic16_emitcode(";remove right +","");
12721
12722   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12723 /*
12724     operand *t = right;
12725     right = nextleft;
12726     nextleft = t; 
12727 */
12728     pic16_emitcode(";remove left +","");
12729   } else
12730     return 0;
12731
12732   big = AOP_SIZE(nextleft);
12733   small = AOP_SIZE(nextright);
12734
12735   switch(nextic->op) {
12736
12737   case '+':
12738     pic16_emitcode(";optimize a +","");
12739     /* if unsigned or not an integral type */
12740     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12741       pic16_emitcode(";add a bit to something","");
12742     } else {
12743
12744       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12745
12746       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12747         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12748         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12749       } else
12750         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12751
12752       offset = 0;
12753       while(--big) {
12754
12755         offset++;
12756
12757         if(--small) {
12758           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12759             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12761           }
12762
12763           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12764           emitSKPNC;
12765           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12766                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12767                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12768           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12769           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12770
12771         } else {
12772           pic16_emitcode("rlf","known_zero,w");
12773
12774           /*
12775             if right is signed
12776               btfsc  right,7
12777                addlw ff
12778           */
12779           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12780             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12781             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12782           } else {
12783             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12784           }
12785         }
12786       }
12787       ret = 1;
12788     }
12789   }
12790   ret = 1;
12791
12792 release:
12793   pic16_freeAsmop(right,NULL,ic,TRUE);
12794   pic16_freeAsmop(result,NULL,ic,TRUE);
12795   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12796   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12797   if(ret)
12798     nextic->generated = 1;
12799
12800   return ret;
12801 #else
12802   return 0;
12803 #endif
12804 }
12805 /*-----------------------------------------------------------------*/
12806 /* genCast - gen code for casting                                  */
12807 /*-----------------------------------------------------------------*/
12808 static void genCast (iCode *ic)
12809 {
12810   operand *result = IC_RESULT(ic);
12811   sym_link *ctype = operandType(IC_LEFT(ic));
12812   sym_link *rtype = operandType(IC_RIGHT(ic));
12813   sym_link *restype = operandType(IC_RESULT(ic));
12814   operand *right = IC_RIGHT(ic);
12815   int size, offset ;
12816
12817
12818     FENTRY;
12819
12820         /* if they are equivalent then do nothing */
12821 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12822 //              return ;
12823
12824         pic16_aopOp(result,ic,FALSE);
12825         pic16_aopOp(right,ic,FALSE) ;
12826
12827         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12828
12829
12830         /* if the result is a bit */
12831         if (AOP_TYPE(result) == AOP_CRY) {
12832         
12833                 /* if the right size is a literal then
12834                  * we know what the value is */
12835                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12836
12837                 if (AOP_TYPE(right) == AOP_LIT) {
12838                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12839                                 pic16_popGet(AOP(result),0));
12840
12841                         if (((int) operandLitValue(right))) 
12842                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12843                                         AOP(result)->aopu.aop_dir,
12844                                         AOP(result)->aopu.aop_dir);
12845                         else
12846                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12847                                         AOP(result)->aopu.aop_dir,
12848                                         AOP(result)->aopu.aop_dir);
12849                         goto release;
12850                 }
12851
12852                 /* the right is also a bit variable */
12853                 if (AOP_TYPE(right) == AOP_CRY) {
12854                         emitCLRC;
12855                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12856
12857                         pic16_emitcode("clrc","");
12858                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12859                                 AOP(right)->aopu.aop_dir,
12860                                 AOP(right)->aopu.aop_dir);
12861                         pic16_aopPut(AOP(result),"c",0);
12862                         goto release ;
12863                 }
12864
12865                 /* we need to or */
12866                 if (AOP_TYPE(right) == AOP_REG) {
12867                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12868                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12869                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12870                 }
12871                 pic16_toBoolean(right);
12872                 pic16_aopPut(AOP(result),"a",0);
12873                 goto release ;
12874         }
12875
12876         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12877           int offset = 1;
12878
12879                 size = AOP_SIZE(result);
12880
12881                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12882
12883                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12884                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12885                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12886
12887                 while (size--)
12888                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12889
12890                 goto release;
12891         }
12892
12893         if(IS_BITFIELD(getSpec(restype))
12894           && IS_BITFIELD(getSpec(rtype))) {
12895           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12896         }
12897         
12898         /* port from pic14 to cope with generic pointers */
12899         if (PIC_IS_TAGGED(restype))
12900         {
12901           operand *result = IC_RESULT(ic);
12902           //operand *left = IC_LEFT(ic);
12903           operand *right = IC_RIGHT(ic);
12904           int tag = 0xff;
12905
12906           /* copy common part */
12907           int max, size = AOP_SIZE(result);
12908           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12909           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12910
12911           max = size;
12912           while (size--)
12913           {
12914             pic16_mov2w (AOP(right), size);
12915             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12916           } // while
12917
12918           /* upcast into generic pointer type? */
12919           if (IS_GENPTR(restype)
12920               && !PIC_IS_TAGGED(rtype)
12921               && (AOP_SIZE(result) > max))
12922           {
12923             /* determine appropriate tag for right */
12924             if (PIC_IS_DATA_PTR(rtype))
12925               tag = GPTR_TAG_DATA;
12926             else if (IS_CODEPTR(rtype))
12927               tag = GPTR_TAG_CODE;
12928             else if (PIC_IS_DATA_PTR(ctype)) {
12929               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12930               tag = GPTR_TAG_DATA;
12931             } else if (IS_CODEPTR(ctype)) {
12932               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12933               tag = GPTR_TAG_CODE;
12934             } else if (IS_PTR(rtype)) {
12935               PERFORM_ONCE(weirdcast,
12936               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12937               );
12938               tag = GPTR_TAG_DATA;
12939             } else {
12940               PERFORM_ONCE(weirdcast,
12941               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12942               );
12943               tag = GPTR_TAG_DATA;
12944             }
12945
12946             assert (AOP_SIZE(result) == 3);
12947             /* zero-extend address... */
12948             for (size = max; size < AOP_SIZE(result)-1; size++)
12949               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12950             /* ...and add tag */
12951             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12952           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12953             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12954             for (size = max; size < AOP_SIZE(result)-1; size++)
12955               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12956             /* add __code tag */
12957             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12958           } else if (AOP_SIZE(result) > max) {
12959             /* extend non-pointers */
12960             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12961             pic16_addSign(result, max, 0);
12962           } // if
12963           goto release;
12964         }
12965
12966         /* if they are the same size : or less */
12967         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12968
12969                 /* if they are in the same place */
12970                 if (pic16_sameRegs(AOP(right),AOP(result)))
12971                         goto release;
12972
12973                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12974 #if 0
12975                 if (IS_PTR_CONST(rtype))
12976 #else
12977                 if (IS_CODEPTR(rtype))
12978 #endif
12979                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12980
12981 #if 0
12982                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12983 #else
12984                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12985 #endif
12986                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12987
12988 #if 0
12989                 if(AOP_TYPE(right) == AOP_IMMD) {
12990                   pCodeOp *pcop0, *pcop1, *pcop2;
12991                   symbol *sym = OP_SYMBOL( right );
12992
12993                         size = AOP_SIZE(result);
12994                         /* low */
12995                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12996                         /* high */
12997                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12998                         /* upper */
12999                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13000         
13001                         if (size == 3) {
13002                                 pic16_emitpcode(POC_MOVLW, pcop0);
13003                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13004                                 pic16_emitpcode(POC_MOVLW, pcop1);
13005                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13006                                 pic16_emitpcode(POC_MOVLW, pcop2);
13007                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13008                         } else
13009                         if (size == 2) {
13010                                 pic16_emitpcode(POC_MOVLW, pcop0);
13011                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13012                                 pic16_emitpcode(POC_MOVLW, pcop1);
13013                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13014                         } else {
13015                                 pic16_emitpcode(POC_MOVLW, pcop0);
13016                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13017                         }
13018                 } else
13019 #endif
13020                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13021                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13022                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13023                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13024                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13025                         if(AOP_SIZE(result) <2)
13026                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13027                 } else {
13028                         /* if they in different places then copy */
13029                         size = AOP_SIZE(result);
13030                         offset = 0 ;
13031                         while (size--) {
13032                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13033                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13034                                 offset++;
13035                         }
13036                 }
13037                 goto release;
13038         }
13039
13040         /* if the result is of type pointer */
13041         if (IS_PTR(ctype)) {
13042           int p_type;
13043           sym_link *type = operandType(right);
13044           sym_link *etype = getSpec(type);
13045
13046                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13047
13048                 /* pointer to generic pointer */
13049                 if (IS_GENPTR(ctype)) {
13050                   char *l = zero;
13051             
13052                         if (IS_PTR(type)) 
13053                                 p_type = DCL_TYPE(type);
13054                         else {
13055                 /* we have to go by the storage class */
13056                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13057
13058 /*              if (SPEC_OCLS(etype)->codesp )  */
13059 /*                  p_type = CPOINTER ;  */
13060 /*              else */
13061 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13062 /*                      p_type = FPOINTER ; */
13063 /*                  else */
13064 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13065 /*                          p_type = PPOINTER; */
13066 /*                      else */
13067 /*                          if (SPEC_OCLS(etype) == idata ) */
13068 /*                              p_type = IPOINTER ; */
13069 /*                          else */
13070 /*                              p_type = POINTER ; */
13071             }
13072                 
13073             /* the first two bytes are known */
13074       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13075             size = GPTRSIZE - 1; 
13076             offset = 0 ;
13077             while (size--) {
13078               if(offset < AOP_SIZE(right)) {
13079                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13080                 pic16_mov2f(AOP(result), AOP(right), offset);
13081 /*
13082                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13083                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13084                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13085                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13086                 } else { 
13087                   
13088                   pic16_aopPut(AOP(result),
13089                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13090                          offset);
13091                 }
13092 */
13093               } else 
13094                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13095               offset++;
13096             }
13097             /* the last byte depending on type */
13098             switch (p_type) {
13099             case IPOINTER:
13100             case POINTER:
13101             case FPOINTER:
13102                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13103                 break;
13104
13105             case CPOINTER:
13106                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13107                 break;
13108
13109             case PPOINTER:
13110               pic16_emitcode(";BUG!? ","%d",__LINE__);
13111                 l = "#0x03";
13112                 break;
13113
13114             case GPOINTER:
13115                 if (GPTRSIZE > AOP_SIZE(right)) {
13116                   // assume __data pointer... THIS MIGHT BE WRONG!
13117                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13118                 } else {
13119                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13120                 }
13121               break;
13122               
13123             default:
13124                 /* this should never happen */
13125                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13126                        "got unknown pointer type");
13127                 exit(1);
13128             }
13129             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13130             goto release ;
13131         }
13132         
13133         
13134         assert( 0 );
13135         /* just copy the pointers */
13136         size = AOP_SIZE(result);
13137         offset = 0 ;
13138         while (size--) {
13139             pic16_aopPut(AOP(result),
13140                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13141                    offset);
13142             offset++;
13143         }
13144         goto release ;
13145     }
13146     
13147
13148
13149     /* so we now know that the size of destination is greater
13150     than the size of the source.
13151     Now, if the next iCode is an operator then we might be
13152     able to optimize the operation without performing a cast.
13153     */
13154     if(genMixedOperation(ic))
13155       goto release;
13156
13157     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13158     
13159     /* we move to result for the size of source */
13160     size = AOP_SIZE(right);
13161     offset = 0 ;
13162
13163     while (size--) {
13164       if(!_G.resDirect)
13165         pic16_mov2f(AOP(result), AOP(right), offset);
13166       offset++;
13167     }
13168
13169     /* now depending on the sign of the destination */
13170     size = AOP_SIZE(result) - AOP_SIZE(right);
13171     /* if unsigned or not an integral type */
13172     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13173       while (size--)
13174         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13175     } else {
13176       /* we need to extend the sign :( */
13177
13178       if(size == 1) {
13179         /* Save one instruction of casting char to int */
13180         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13181         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13182         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13183       } else {
13184         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13185
13186         if(offset)
13187           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13188         else
13189           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13190         
13191         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13192
13193         while (size--)
13194           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13195       }
13196     }
13197
13198 release:
13199     pic16_freeAsmop(right,NULL,ic,TRUE);
13200     pic16_freeAsmop(result,NULL,ic,TRUE);
13201
13202 }
13203
13204 /*-----------------------------------------------------------------*/
13205 /* genDjnz - generate decrement & jump if not zero instrucion      */
13206 /*-----------------------------------------------------------------*/
13207 static int genDjnz (iCode *ic, iCode *ifx)
13208 {
13209     symbol *lbl, *lbl1;
13210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13211
13212     if (!ifx)
13213         return 0;
13214     
13215     /* if the if condition has a false label
13216        then we cannot save */
13217     if (IC_FALSE(ifx))
13218         return 0;
13219
13220     /* if the minus is not of the form 
13221        a = a - 1 */
13222     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13223         !IS_OP_LITERAL(IC_RIGHT(ic)))
13224         return 0;
13225
13226     if (operandLitValue(IC_RIGHT(ic)) != 1)
13227         return 0;
13228
13229     /* if the size of this greater than one then no
13230        saving */
13231     if (getSize(operandType(IC_RESULT(ic))) > 1)
13232         return 0;
13233
13234     /* otherwise we can save BIG */
13235     lbl = newiTempLabel(NULL);
13236     lbl1= newiTempLabel(NULL);
13237
13238     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13239     
13240     if (IS_AOP_PREG(IC_RESULT(ic))) {
13241         pic16_emitcode("dec","%s",
13242                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13243         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13244         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13245     } else {    
13246
13247
13248       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13249       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13250
13251       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13252       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13253
13254     }
13255     
13256     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13257     ifx->generated = 1;
13258     return 1;
13259 }
13260
13261 /*-----------------------------------------------------------------*/
13262 /* genReceive - generate code for a receive iCode                  */
13263 /*-----------------------------------------------------------------*/
13264 static void genReceive (iCode *ic)
13265 {    
13266
13267   FENTRY;
13268
13269 #if 0
13270   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13271         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13272 #endif
13273 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13274
13275   if (isOperandInFarSpace(IC_RESULT(ic))
13276       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13277           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13278
13279     int size = getSize(operandType(IC_RESULT(ic)));
13280     int offset =  pic16_fReturnSizePic - size;
13281
13282       assert( 0 );
13283       while (size--) {
13284         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13285                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13286                       offset++;
13287         }
13288
13289       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13290
13291       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13292       size = AOP_SIZE(IC_RESULT(ic));
13293       offset = 0;
13294       while (size--) {
13295         pic16_emitcode ("pop","acc");
13296         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13297       }
13298   } else {
13299     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13300     _G.accInUse++;
13301     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13302     _G.accInUse--;
13303
13304     /* set pseudo stack pointer to where it should be - dw*/
13305     GpsuedoStkPtr = ic->parmBytes;
13306
13307     /* setting GpsuedoStkPtr has side effects here: */
13308     assignResultValue(IC_RESULT(ic), 0);
13309   }
13310
13311   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13312 }
13313
13314 /*-----------------------------------------------------------------*/
13315 /* genDummyRead - generate code for dummy read of volatiles        */
13316 /*-----------------------------------------------------------------*/
13317 static void
13318 genDummyRead (iCode * ic)
13319 {
13320   operand *op;
13321   int i;
13322
13323   op = IC_RIGHT(ic);
13324   if (op && IS_SYMOP(op)) {
13325     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13326       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13327       return;
13328     }
13329     pic16_aopOp (op, ic, FALSE);
13330     for (i=0; i < AOP_SIZE(op); i++) {
13331       // may need to protect this from the peepholer -- this is not nice but works...
13332       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13333       pic16_mov2w (AOP(op),i);
13334       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13335     } // for i
13336     pic16_freeAsmop (op, NULL, ic, TRUE);
13337   } else if (op) {
13338     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13339   } // if
13340 }
13341
13342 /*-----------------------------------------------------------------*/
13343 /* genpic16Code - generate code for pic16 based controllers        */
13344 /*-----------------------------------------------------------------*/
13345 /*
13346  * At this point, ralloc.c has gone through the iCode and attempted
13347  * to optimize in a way suitable for a PIC. Now we've got to generate
13348  * PIC instructions that correspond to the iCode.
13349  *
13350  * Once the instructions are generated, we'll pass through both the
13351  * peep hole optimizer and the pCode optimizer.
13352  *-----------------------------------------------------------------*/
13353
13354 void genpic16Code (iCode *lic)
13355 {
13356   iCode *ic;
13357   int cln = 0;
13358
13359     lineHead = lineCurr = NULL;
13360
13361     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13362     pic16_addpBlock(pb);
13363
13364 #if 0
13365     /* if debug information required */
13366     if (options.debug && currFunc) {
13367       if (currFunc) {
13368         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13369       }
13370     }
13371 #endif
13372
13373     for (ic = lic ; ic ; ic = ic->next ) {
13374
13375       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13376       if ( cln != ic->lineno ) {
13377         if ( options.debug ) {
13378           debugFile->writeCLine (ic);
13379         }
13380         
13381         if(!options.noCcodeInAsm) {
13382           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13383               printCLine(ic->filename, ic->lineno)));
13384         }
13385
13386         cln = ic->lineno ;
13387       }
13388         
13389       if(options.iCodeInAsm) {
13390         char *l;
13391
13392           /* insert here code to print iCode as comment */
13393           l = Safe_strdup(printILine(ic));
13394           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13395       }
13396
13397       /* if the result is marked as
13398        * spilt and rematerializable or code for
13399        * this has already been generated then
13400        * do nothing */
13401       if (resultRemat(ic) || ic->generated ) 
13402         continue ;
13403         
13404       /* depending on the operation */
13405       switch (ic->op) {
13406         case '!' :
13407           pic16_genNot(ic);
13408           break;
13409             
13410         case '~' :
13411           pic16_genCpl(ic);
13412           break;
13413             
13414         case UNARYMINUS:
13415           genUminus (ic);
13416           break;
13417             
13418         case IPUSH:
13419           genIpush (ic);
13420           break;
13421             
13422         case IPOP:
13423           /* IPOP happens only when trying to restore a 
13424            * spilt live range, if there is an ifx statement
13425            * following this pop then the if statement might
13426            * be using some of the registers being popped which
13427            * would destroy the contents of the register so
13428            * we need to check for this condition and handle it */
13429            if (ic->next
13430              && ic->next->op == IFX
13431              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13432                genIfx (ic->next,ic);
13433           else
13434             genIpop (ic);
13435           break; 
13436             
13437         case CALL:
13438           genCall (ic);
13439           break;
13440             
13441         case PCALL:
13442           genPcall (ic);
13443           break;
13444             
13445         case FUNCTION:
13446           genFunction (ic);
13447           break;
13448             
13449         case ENDFUNCTION:
13450           genEndFunction (ic);
13451           break;
13452             
13453         case RETURN:
13454           genRet (ic);
13455           break;
13456             
13457         case LABEL:
13458           genLabel (ic);
13459           break;
13460             
13461         case GOTO:
13462           genGoto (ic);
13463           break;
13464             
13465         case '+' :
13466           pic16_genPlus (ic) ;
13467           break;
13468             
13469         case '-' :
13470           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13471             pic16_genMinus (ic);
13472           break;
13473
13474         case '*' :
13475           genMult (ic);
13476           break;
13477             
13478         case '/' :
13479           genDiv (ic) ;
13480           break;
13481             
13482         case '%' :
13483           genMod (ic);
13484           break;
13485             
13486         case '>' :
13487           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13488           break;
13489             
13490         case '<' :
13491           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13492           break;
13493             
13494         case LE_OP:
13495         case GE_OP:
13496         case NE_OP:
13497           /* note these two are xlated by algebraic equivalence
13498            * during parsing SDCC.y */
13499           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13500             "got '>=' or '<=' shouldn't have come here");
13501           break;
13502
13503         case EQ_OP:
13504           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13505           break;            
13506             
13507         case AND_OP:
13508           genAndOp (ic);
13509           break;
13510             
13511         case OR_OP:
13512           genOrOp (ic);
13513           break;
13514             
13515         case '^' :
13516           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13517           break;
13518             
13519         case '|' :
13520           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13521           break;
13522             
13523         case BITWISEAND:
13524           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13525           break;
13526             
13527         case INLINEASM:
13528           genInline (ic);
13529           break;
13530             
13531         case RRC:
13532           genRRC (ic);
13533           break;
13534             
13535         case RLC:
13536           genRLC (ic);
13537           break;
13538             
13539         case GETHBIT:
13540           genGetHbit (ic);
13541           break;
13542             
13543         case LEFT_OP:
13544           genLeftShift (ic);
13545           break;
13546             
13547         case RIGHT_OP:
13548           genRightShift (ic);
13549           break;
13550             
13551         case GET_VALUE_AT_ADDRESS:
13552           genPointerGet(ic);
13553           break;
13554             
13555         case '=' :
13556           if (POINTER_SET(ic))
13557             genPointerSet(ic);
13558           else
13559             genAssign(ic);
13560           break;
13561             
13562         case IFX:
13563           genIfx (ic,NULL);
13564           break;
13565             
13566         case ADDRESS_OF:
13567           genAddrOf (ic);
13568           break;
13569             
13570         case JUMPTABLE:
13571           genJumpTab (ic);
13572           break;
13573             
13574         case CAST:
13575           genCast (ic);
13576           break;
13577             
13578         case RECEIVE:
13579           genReceive(ic);
13580           break;
13581             
13582         case SEND:
13583           addSet(&_G.sendSet,ic);
13584           break;
13585
13586         case DUMMY_READ_VOLATILE:
13587           genDummyRead (ic);
13588           break;
13589
13590         default :
13591           ic = ic;
13592       }
13593     }
13594
13595
13596     /* now we are ready to call the
13597        peep hole optimizer */
13598     if (!options.nopeep)
13599       peepHole (&lineHead);
13600
13601     /* now do the actual printing */
13602     printLine (lineHead, codeOutFile);
13603
13604 #ifdef PCODE_DEBUG
13605     DFPRINTF((stderr,"printing pBlock\n\n"));
13606     pic16_printpBlock(stdout,pb);
13607 #endif
13608
13609     return;
13610 }
13611