* src/pic16/pcode.c (pic16_newpCodeOpLit12),
[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@otenet.gr (2003,2004,2005)
10   Bug Fixes  -  Raphael Neider rneider@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           for(i=0;i<aop->size;i++) {
711             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
712             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
713           }
714         }
715
716
717 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
718
719 #if 1
720         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
721
722         // we do not need to load the value if it is to be defined...
723         if (result) return aop;
724
725         if(_G.accInUse) {
726                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
727         }
728         
729         for(i=0;i<aop->size;i++) {
730
731           /* initialise for stack access via frame pointer */
732           // operands on stack are accessible via "{FRAME POINTER} + index" with index
733           // starting at 2 for arguments and growing from 0 downwards for
734           // local variables (index == 0 is not assigned so we add one here)
735           {
736             int soffs = sym->stack;
737             if (soffs <= 0) {
738               assert (soffs < 0);
739               soffs++;
740             } // if
741
742             if(1 && ic->op == SEND) {
743               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
744               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
745                     pic16_popCopyReg( pic16_frame_plusw ),
746                     pic16_popCopyReg(pic16_stack_postdec )));
747             } else {
748               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
749               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
750                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
751             }
752           }
753         }
754         
755         if(_G.accInUse) {
756                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
757         }
758         
759         return (aop);
760 #endif
761
762 #if 0
763         /* now assign the address of the variable to 
764         the pointer register */
765         if (aop->type != AOP_STK) {
766
767             if (sym->onStack) {
768                     if ( _G.accInUse )
769                         pic16_emitcode("push","acc");
770
771                     pic16_emitcode("mov","a,_bp");
772                     pic16_emitcode("add","a,#0x%02x",
773                              ((sym->stack < 0) ?
774                               ((char)(sym->stack - _G.nRegsSaved )) :
775                               ((char)sym->stack)) & 0xff);
776                     pic16_emitcode("mov","%s,a",
777                              aop->aopu.aop_ptr->name);
778
779                     if ( _G.accInUse )
780                         pic16_emitcode("pop","acc");
781             } else
782                 pic16_emitcode("mov","%s,#%s",
783                          aop->aopu.aop_ptr->name,
784                          sym->rname);
785             aop->paged = space->paged;
786         } else
787             aop->aopu.aop_stk = sym->stack;
788         return aop;
789 #endif
790
791     }
792 #endif
793
794 #if 0
795     if (sym->onStack && options.stack10bit)
796     {
797         /* It's on the 10 bit stack, which is located in
798          * far data space.
799          */
800          
801       //DEBUGpic16_emitcode(";","%d",__LINE__);
802
803         if ( _G.accInUse )
804                 pic16_emitcode("push","acc");
805
806         pic16_emitcode("mov","a,_bp");
807         pic16_emitcode("add","a,#0x%02x",
808                  ((sym->stack < 0) ?
809                    ((char)(sym->stack - _G.nRegsSaved )) :
810                    ((char)sym->stack)) & 0xff);
811         
812         genSetDPTR(1);
813         pic16_emitcode ("mov","dpx1,#0x40");
814         pic16_emitcode ("mov","dph1,#0x00");
815         pic16_emitcode ("mov","dpl1, a");
816         genSetDPTR(0);
817         
818         if ( _G.accInUse )
819             pic16_emitcode("pop","acc");
820             
821         sym->aop = aop = newAsmop(AOP_DPTR2);
822         aop->size = getSize(sym->type); 
823         return aop;
824     }
825 #endif
826
827 #if 1
828     /* special case for a function */
829     if (IS_FUNC(sym->type)) {   
830         sym->aop = aop = newAsmop(AOP_PCODE);
831         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
832         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
833         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
834         PCOI(aop->aopu.pcop)->index = 0;
835         aop->size = FPTRSIZE; 
836         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
837         return aop;
838     }
839 #endif
840
841
842
843     //DEBUGpic16_emitcode(";","%d",__LINE__);
844     /* if in bit space */
845     if (IN_BITSPACE(space)) {
846         sym->aop = aop = newAsmop (AOP_CRY);
847         aop->aopu.aop_dir = sym->rname ;
848         aop->size = getSize(sym->type);
849         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
850         return aop;
851     }
852     /* if it is in direct space */
853     if (IN_DIRSPACE(space)) {
854                 if(!strcmp(sym->rname, "_WREG")) {
855                         sym->aop = aop = newAsmop (AOP_ACC);
856                         aop->size = getSize(sym->type);         /* should always be 1 */
857                         assert(aop->size == 1);
858                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
859                         return (aop);
860                 } else {
861                         sym->aop = aop = newAsmop (AOP_DIR);
862                 aop->aopu.aop_dir = sym->rname ;
863             aop->size = getSize(sym->type);
864                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
865                         pic16_allocDirReg( IC_LEFT(ic) );
866                         return (aop);
867                 }
868         }
869
870     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
871         sym->aop = aop = newAsmop (AOP_DIR);
872         aop->aopu.aop_dir = sym->rname ;
873         aop->size = getSize(sym->type);
874         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
875         pic16_allocDirReg( IC_LEFT(ic) );
876         return aop;
877     }
878
879
880     /* only remaining is far space */
881     sym->aop = aop = newAsmop(AOP_PCODE);
882
883 /* change the next if to 1 to revert to good old immediate code */
884         if(IN_CODESPACE(space)) {
885                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
886                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
887                 PCOI(aop->aopu.pcop)->index = 0;
888         } else {
889                 /* try to allocate via direct register */
890                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
891 //              aop->size = getSize( sym->type );
892         }
893
894         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
895                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
896
897 #if 0
898         if(!pic16_allocDirReg (IC_LEFT(ic)))
899                 return NULL;
900 #endif
901
902         if(IN_DIRSPACE( space ))
903                 aop->size = PTRSIZE;
904         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
905                 aop->size = FPTRSIZE;
906         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
907         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
908         else if(sym->onStack) {
909                 aop->size = PTRSIZE;
910         } else {
911           if(SPEC_SCLS(sym->etype) == S_PDATA) {
912             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
913             aop->size = FPTRSIZE;
914           } else
915                 assert( 0 );
916         }
917
918     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
919
920     /* if it is in code space */
921     if (IN_CODESPACE(space))
922         aop->code = 1;
923
924     return aop;     
925 }
926
927 /*-----------------------------------------------------------------*/
928 /* aopForRemat - rematerialzes an object                           */
929 /*-----------------------------------------------------------------*/
930 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
931 {
932   symbol *sym = OP_SYMBOL(op);
933   operand *refop;
934   iCode *ic = NULL, *oldic;
935   asmop *aop = newAsmop(AOP_PCODE);
936   int val = 0;
937   int offset = 0;
938   int viaimmd=0;
939
940     FENTRY2;
941     
942         ic = sym->rematiCode;
943
944         if(IS_OP_POINTER(op)) {
945                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
946         }
947
948 //    if(!result)               /* fixme-vr */
949         for (;;) {
950                 oldic = ic;
951
952 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
953         
954                 if (ic->op == '+') {
955                         val += (int) operandLitValue(IC_RIGHT(ic));
956                 } else if (ic->op == '-') {
957                         val -= (int) operandLitValue(IC_RIGHT(ic));
958                 } else
959                         break;
960                 
961                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
962         }
963
964         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
965         refop = IC_LEFT(ic);
966
967         if(!op->isaddr)viaimmd++; else viaimmd=0;
968                 
969 /* set the following if to 1 to revert to good old immediate code */
970         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
971                 || viaimmd) {
972
973                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
974
975                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
976
977 #if 0
978                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
979 #else
980                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
981 #endif
982
983                 PCOI(aop->aopu.pcop)->index = val;
984                 
985                 aop->size = getSize( sym->type );
986         } else {
987                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
988
989                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
990                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
991
992                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
993         }
994
995
996         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
997                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
998 #if 0
999                 val, IS_PTR_CONST(operandType(op)));
1000 #else
1001                 val, IS_CODEPTR(operandType(op)));
1002 #endif
1003
1004 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1005
1006         pic16_allocDirReg (IC_LEFT(ic));
1007
1008         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1009                 aop->code = 1;
1010
1011   return aop;        
1012 }
1013
1014 #if 0
1015 static int aopIdx (asmop *aop, int offset)
1016 {
1017   if(!aop)
1018     return -1;
1019
1020   if(aop->type !=  AOP_REG)
1021     return -2;
1022         
1023   return aop->aopu.aop_reg[offset]->rIdx;
1024
1025 }
1026 #endif
1027
1028 /*-----------------------------------------------------------------*/
1029 /* regsInCommon - two operands have some registers in common       */
1030 /*-----------------------------------------------------------------*/
1031 static bool regsInCommon (operand *op1, operand *op2)
1032 {
1033     symbol *sym1, *sym2;
1034     int i;
1035
1036     /* if they have registers in common */
1037     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1038         return FALSE ;
1039
1040     sym1 = OP_SYMBOL(op1);
1041     sym2 = OP_SYMBOL(op2);
1042
1043     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1044         return FALSE ;
1045
1046     for (i = 0 ; i < sym1->nRegs ; i++) {
1047         int j;
1048         if (!sym1->regs[i])
1049             continue ;
1050
1051         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1052             if (!sym2->regs[j])
1053                 continue ;
1054
1055             if (sym2->regs[j] == sym1->regs[i])
1056                 return TRUE ;
1057         }
1058     }
1059
1060     return FALSE ;
1061 }
1062
1063 /*-----------------------------------------------------------------*/
1064 /* operandsEqu - equivalent                                        */
1065 /*-----------------------------------------------------------------*/
1066 static bool operandsEqu ( operand *op1, operand *op2)
1067 {
1068     symbol *sym1, *sym2;
1069
1070     /* if they not symbols */
1071     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1072         return FALSE;
1073
1074     sym1 = OP_SYMBOL(op1);
1075     sym2 = OP_SYMBOL(op2);
1076
1077     /* if both are itemps & one is spilt
1078        and the other is not then false */
1079     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1080         sym1->isspilt != sym2->isspilt )
1081         return FALSE ;
1082
1083     /* if they are the same */
1084     if (sym1 == sym2)
1085         return TRUE ;
1086
1087     if (sym1->rname[0] && sym2->rname[0]
1088         && strcmp (sym1->rname, sym2->rname) == 0)
1089         return TRUE;
1090
1091
1092     /* if left is a tmp & right is not */
1093     if (IS_ITEMP(op1)  && 
1094         !IS_ITEMP(op2) &&
1095         sym1->isspilt  &&
1096         (sym1->usl.spillLoc == sym2))
1097         return TRUE;
1098
1099     if (IS_ITEMP(op2)  && 
1100         !IS_ITEMP(op1) &&
1101         sym2->isspilt  &&
1102         sym1->level > 0 &&
1103         (sym2->usl.spillLoc == sym1))
1104         return TRUE ;
1105
1106     return FALSE ;
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_sameRegs - two asmops have the same registers                   */
1111 /*-----------------------------------------------------------------*/
1112 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1113 {
1114     int i;
1115
1116     if (aop1 == aop2)
1117         return TRUE ;
1118
1119     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1120                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1121
1122     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1123
1124     if (aop1->type != AOP_REG ||
1125         aop2->type != AOP_REG )
1126         return FALSE ;
1127
1128     /* This is a bit too restrictive if one is a subset of the other...
1129     if (aop1->size != aop2->size )
1130         return FALSE ;
1131     */
1132
1133     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1134 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1135
1136 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1137         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1138             return FALSE ;
1139     }
1140
1141     return TRUE ;
1142 }
1143
1144 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1145 {
1146     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1147                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1148
1149     if(aop1 == aop2)return TRUE;
1150     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1151       
1152       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1153     
1154   return TRUE;
1155 }
1156
1157
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1160 /*-----------------------------------------------------------------*/
1161 void pic16_aopOp (operand *op, iCode *ic, bool result)
1162 {
1163     asmop *aop;
1164     symbol *sym;
1165     int i;
1166
1167     if (!op)
1168         return ;
1169
1170     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1171
1172     /* if this a literal */
1173     if (IS_OP_LITERAL(op)) {
1174         op->aop = aop = newAsmop(AOP_LIT);
1175         aop->aopu.aop_lit = op->operand.valOperand;
1176         aop->size = getSize(operandType(op));
1177         return;
1178     }
1179
1180     {
1181       sym_link *type = operandType(op);
1182 #if 0
1183       if(IS_PTR_CONST(type))
1184 #else
1185       if(IS_CODEPTR(type))
1186 #endif
1187         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1188     }
1189
1190     /* if already has a asmop then continue */
1191     if (op->aop)
1192         return ;
1193
1194     /* if the underlying symbol has a aop */
1195     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1196       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1197         op->aop = OP_SYMBOL(op)->aop;
1198         return;
1199     }
1200
1201     /* if this is a true symbol */
1202     if (IS_TRUE_SYMOP(op)) {    
1203         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1204       op->aop = aopForSym(ic, op, result);
1205       return ;
1206     }
1207
1208     /* this is a temporary : this has
1209     only four choices :
1210     a) register
1211     b) spillocation
1212     c) rematerialize 
1213     d) conditional   
1214     e) can be a return use only */
1215
1216     sym = OP_SYMBOL(op);
1217
1218     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1219     /* if the type is a conditional */
1220     if (sym->regType == REG_CND) {
1221         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1222         aop->size = 0;
1223         return;
1224     }
1225
1226     /* if it is spilt then two situations
1227     a) is rematerialize 
1228     b) has a spill location */
1229     if (sym->isspilt || sym->nRegs == 0) {
1230
1231 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1232       DEBUGpic16_emitcode(";","%d",__LINE__);
1233         /* rematerialize it NOW */
1234         if (sym->remat) {
1235
1236             sym->aop = op->aop = aop = aopForRemat (op, result);
1237 //            aop->size = getSize(sym->type);
1238 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1239             return;
1240         }
1241
1242 #if 1
1243         if (sym->accuse) {
1244             int i;
1245             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1246             aop->size = getSize(sym->type);
1247             for ( i = 0 ; i < 1 ; i++ ) {
1248                 aop->aopu.aop_str[i] = accUse[i];
1249 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1250             }
1251             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1252             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1253             return;  
1254         }
1255 #endif
1256
1257 #if 1
1258         if (sym->ruonly) {
1259           /*
1260           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1261           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1262           //pic16_allocDirReg (IC_LEFT(ic));
1263           aop->size = getSize(sym->type);
1264           */
1265
1266           unsigned i;
1267
1268           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1269           aop->size = getSize(sym->type);
1270           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1271             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1272
1273           DEBUGpic16_emitcode(";","%d",__LINE__);
1274           return;
1275         }
1276 #endif
1277         /* else spill location  */
1278         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1279             /* force a new aop if sizes differ */
1280             sym->usl.spillLoc->aop = NULL;
1281         }
1282
1283 #if 0
1284         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1285                             __FUNCTION__,__LINE__,
1286                             sym->usl.spillLoc->rname,
1287                             sym->rname, sym->usl.spillLoc->offset);
1288 #endif
1289
1290         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1291         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1294                                                   getSize(sym->type), 
1295                                                   sym->usl.spillLoc->offset, op);
1296         } else {
1297           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1298           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1299           assert (getSize(sym->type) <= 1);
1300           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1301         }
1302         aop->size = getSize(sym->type);
1303
1304         return;
1305     }
1306
1307     {
1308       sym_link *type = operandType(op);
1309 #if 0
1310       if(IS_PTR_CONST(type)) 
1311 #else
1312       if(IS_CODEPTR(type)) 
1313 #endif
1314         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1315     }
1316
1317     /* must be in a register */
1318     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1319     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1320     aop->size = sym->nRegs;
1321     for ( i = 0 ; i < sym->nRegs ;i++)
1322         aop->aopu.aop_reg[i] = sym->regs[i];
1323 }
1324
1325 /*-----------------------------------------------------------------*/
1326 /* pic16_freeAsmop - free up the asmop given to an operand               */
1327 /*----------------------------------------------------------------*/
1328 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1329 {   
1330     asmop *aop ;
1331
1332     if (!op)
1333         aop = aaop;
1334     else 
1335         aop = op->aop;
1336
1337     if (!aop)
1338         return ;
1339
1340     if (aop->freed)
1341         goto dealloc; 
1342
1343     aop->freed = 1;
1344
1345     /* depending on the asmop type only three cases need work AOP_RO
1346        , AOP_R1 && AOP_STK */
1347 #if 1
1348     switch (aop->type) {
1349         case AOP_FSR0 :
1350             if (_G.fsr0Pushed ) {
1351                 if (pop) {
1352                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1353                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1354 //                    pic16_emitcode ("pop","ar0");
1355                     _G.fsr0Pushed--;
1356                 }
1357             }
1358             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1359             break;
1360
1361         case AOP_FSR2 :
1362             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1363             break;
1364
1365         case AOP_R0 :
1366             if (_G.r0Pushed ) {
1367                 if (pop) {
1368                     pic16_emitcode ("pop","ar0");     
1369                     _G.r0Pushed--;
1370                 }
1371             }
1372             bitVectUnSetBit(ic->rUsed,R0_IDX);
1373             break;
1374
1375         case AOP_R1 :
1376             if (_G.r1Pushed ) {
1377                 if (pop) {
1378                     pic16_emitcode ("pop","ar1");
1379                     _G.r1Pushed--;
1380                 }
1381             }
1382             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1383             break;
1384
1385         case AOP_STA:
1386           {
1387             int i;
1388
1389               /* we must store the result on stack */
1390               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1391                 // operands on stack are accessible via "FSR2 + index" with index
1392                 // starting at 2 for arguments and growing from 0 downwards for
1393                 // local variables (index == 0 is not assigned so we add one here)
1394                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1395                 if (soffs <= 0) {
1396                   assert (soffs < 0);
1397                   soffs++;
1398                 } // if
1399                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1400                 for(i=0;i<aop->size;i++) {
1401                   /* initialise for stack access via frame pointer */
1402                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1403                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1404                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1405                 }
1406         
1407                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1408               }
1409
1410               if(!_G.resDirect) {
1411                 for(i=0;i<aop->size;i++) {
1412                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1413
1414                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1415                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1416                 }
1417                   
1418               }
1419               _G.resDirect = 0;
1420           }
1421           break;
1422 #if 0
1423         case AOP_STK :
1424         {
1425             int sz = aop->size;    
1426             int stk = aop->aopu.aop_stk + aop->size;
1427             bitVectUnSetBit(ic->rUsed,R0_IDX);
1428             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1429
1430             getFreePtr(ic,&aop,FALSE);
1431             
1432             if (options.stack10bit)
1433             {
1434                 /* I'm not sure what to do here yet... */
1435                 /* #STUB */
1436                 fprintf(stderr, 
1437                         "*** Warning: probably generating bad code for "
1438                         "10 bit stack mode.\n");
1439             }
1440             
1441             if (stk) {
1442                 pic16_emitcode ("mov","a,_bp");
1443                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1444                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1445             } else {
1446                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1447             }
1448
1449             while (sz--) {
1450                 pic16_emitcode("pop","acc");
1451                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1452                 if (!sz) break;
1453                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1454             }
1455             op->aop = aop;
1456             pic16_freeAsmop(op,NULL,ic,TRUE);
1457             if (_G.r0Pushed) {
1458                 pic16_emitcode("pop","ar0");
1459                 _G.r0Pushed--;
1460             }
1461
1462             if (_G.r1Pushed) {
1463                 pic16_emitcode("pop","ar1");
1464                 _G.r1Pushed--;
1465             }       
1466         }
1467 #endif
1468
1469     }
1470 #endif
1471
1472 dealloc:
1473     /* all other cases just dealloc */
1474     if (op ) {
1475         op->aop = NULL;
1476         if (IS_SYMOP(op)) {
1477             OP_SYMBOL(op)->aop = NULL;    
1478             /* if the symbol has a spill */
1479             if (SPIL_LOC(op))
1480                 SPIL_LOC(op)->aop = NULL;
1481         }
1482     }
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_aopGet - for fetching value of the aop                          */
1487 /*-----------------------------------------------------------------*/
1488 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1489 {
1490     char *s = buffer ;
1491     char *rs;
1492
1493     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1494
1495     /* offset is greater than size then zero */
1496     if (offset > (aop->size - 1) &&
1497         aop->type != AOP_LIT)
1498         return zero;
1499
1500     /* depending on type */
1501     switch (aop->type) {
1502
1503     case AOP_FSR0:
1504     case AOP_FSR2:
1505       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1506       rs = Safe_calloc(1, strlen(s)+1);
1507       strcpy(rs, s);
1508       return (rs);
1509       
1510 #if 0
1511       /* if we need to increment it */
1512       while (offset > aop->coff)
1513         {
1514           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1515           aop->coff++;
1516         }
1517
1518       while (offset < aop->coff)
1519         {
1520           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1521           aop->coff--;
1522         }
1523       aop->coff = offset;
1524       if (aop->paged)
1525         {
1526           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1527           return (dname ? "acc" : "a");
1528         }
1529       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1530       rs = Safe_calloc (1, strlen (s) + 1);
1531       strcpy (rs, s);
1532       return rs;
1533 #endif
1534
1535         
1536     case AOP_IMMD:
1537         if (bit16) 
1538             sprintf (s,"%s",aop->aopu.aop_immd);
1539         else
1540             if (offset) 
1541                 sprintf(s,"(%s >> %d)",
1542                         aop->aopu.aop_immd,
1543                         offset*8);
1544             else
1545                 sprintf(s,"%s",
1546                         aop->aopu.aop_immd);
1547         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1548         rs = Safe_calloc(1,strlen(s)+1);
1549         strcpy(rs,s);   
1550         return rs;
1551         
1552     case AOP_DIR:
1553       if (offset) {
1554         sprintf(s,"(%s + %d)",
1555                 aop->aopu.aop_dir,
1556                 offset);
1557         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1558       } else
1559             sprintf(s,"%s",aop->aopu.aop_dir);
1560         rs = Safe_calloc(1,strlen(s)+1);
1561         strcpy(rs,s);   
1562         return rs;
1563         
1564     case AOP_REG:
1565       return aop->aopu.aop_reg[offset]->name;
1566         
1567     case AOP_CRY:
1568       return aop->aopu.aop_dir;
1569         
1570     case AOP_ACC:
1571         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1572 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1573 //        assert( 0 );
1574 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1575         rs = Safe_strdup("WREG");
1576         return (rs);
1577
1578     case AOP_LIT:
1579         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1580         rs = Safe_calloc(1,strlen(s)+1);
1581         strcpy(rs,s);   
1582         return rs;
1583         
1584     case AOP_STR:
1585         aop->coff = offset ;
1586
1587 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1588 //          dname)
1589 //          return "acc";
1590         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1591           aop->type = AOP_ACC;
1592           return Safe_strdup("_WREG");
1593         }
1594         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1595         
1596         return aop->aopu.aop_str[offset];
1597         
1598     case AOP_PCODE:
1599       {
1600         pCodeOp *pcop = aop->aopu.pcop;
1601         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1602         if(pcop->name) {
1603           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1604           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1605           if (offset) {
1606             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1607           } else {
1608             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1609           }
1610         } else
1611           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1612
1613       }
1614       rs = Safe_calloc(1,strlen(s)+1);
1615       strcpy(rs,s);   
1616       return rs;
1617
1618 #if 0
1619     case AOP_PAGED:
1620       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1621       if (offset) {
1622         sprintf(s,"(%s + %d)",
1623                 aop->aopu.aop_dir,
1624                 offset);
1625       } else
1626             sprintf(s,"%s",aop->aopu.aop_dir);
1627       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1628       rs = Safe_calloc(1,strlen(s)+1);
1629       strcpy(rs,s);   
1630       return rs;
1631 #endif
1632
1633     case AOP_STA:
1634         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1635         return (rs);
1636         
1637     case AOP_STK:
1638 //        pCodeOp *pcop = aop->aop
1639         break;
1640
1641     }
1642
1643     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1644     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1645            "aopget got unsupported aop->type");
1646     exit(0);
1647 }
1648
1649
1650
1651 /* lock has the following meaning: When allocating temporary registers
1652  * for stack variables storage, the value of the temporary register is
1653  * saved on stack. Its value is restored at the end. This procedure is
1654  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1655  * a possibility that before a call to pic16_aopOp, a temporary register
1656  * is allocated for a while and it is freed after some time, this will
1657  * mess the stack and values will not be restored properly. So use lock=1
1658  * to allocate temporary registers used internally by the programmer, and
1659  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1660  * to inform the compiler developer about a possible bug. This is an internal
1661  * feature for developing the compiler -- VR */
1662  
1663 int _TempReg_lock = 0;
1664 /*-----------------------------------------------------------------*/
1665 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1666 /*-----------------------------------------------------------------*/
1667 pCodeOp *pic16_popGetTempReg(int lock)
1668 {
1669   pCodeOp *pcop=NULL;
1670   symbol *cfunc;
1671
1672 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1673     if(_TempReg_lock) {
1674 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1675     }
1676     
1677     _TempReg_lock += lock;
1678     
1679     cfunc = currFunc;
1680     currFunc = NULL;
1681
1682 #if 0
1683         {
1684           regs *rr;
1685           int i;
1686
1687                 /* this code might seem better but it does the *same* job with
1688                  * the old code, it all depends on ralloc.c to get a free/unused
1689                  * register */
1690          
1691                 i=0;
1692                 while(i < pic16_nRegs) {
1693                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1694                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1695                         if((!rr || (rr && rr->isFree))
1696                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1697                                 pcop = pic16_newpCodeOpReg( i );
1698                                 PCOR(pcop)->r->wasUsed = 1;
1699                                 PCOR(pcop)->r->isFree = 0;
1700                                 break;
1701                         }
1702                         i++;
1703                 }
1704
1705                 if(pcop) {
1706                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1707                 }
1708         }
1709 #else
1710     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1711     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1712       PCOR(pcop)->r->wasUsed=1;
1713       PCOR(pcop)->r->isFree=0;
1714
1715       /* push value on stack */
1716       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1717     }
1718 #endif
1719
1720     currFunc = cfunc;
1721
1722   return pcop;
1723 }
1724
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1727 /*                           is not part of f, but don't save if   */
1728 /*                           inside v                              */
1729 /*-----------------------------------------------------------------*/
1730 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1731 {
1732   pCodeOp *pcop=NULL;
1733   symbol *cfunc;
1734   int i;
1735
1736 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1737
1738     if(_TempReg_lock) {
1739 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1740     }
1741
1742     _TempReg_lock += lock;
1743
1744     cfunc = currFunc;
1745     currFunc = NULL;
1746
1747     i = bitVectFirstBit(f);
1748     while(i < 128) {
1749
1750       /* bypass registers that are used by function */
1751       if(!bitVectBitValue(f, i)) {
1752       
1753         /* bypass registers that are already allocated for stack access */
1754         if(!bitVectBitValue(v, i))  {
1755         
1756 //          debugf("getting register rIdx = %d\n", i);
1757           /* ok, get the operand */
1758           pcop = pic16_newpCodeOpReg( i );
1759     
1760           /* should never by NULL */
1761           assert( pcop != NULL );
1762
1763           
1764           /* sanity check */
1765           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1766             int found=0;
1767             
1768               PCOR(pcop)->r->wasUsed=1;
1769               PCOR(pcop)->r->isFree=0;
1770
1771
1772               {
1773                 regs *sr;
1774               
1775                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1776
1777                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1778                       /* already used in previous steps, break */
1779                       found=1;          
1780                       break;
1781                     }
1782                   }
1783               }
1784
1785               /* caller takes care of the following */
1786 //              bitVectSetBit(v, i);
1787
1788               if(!found) {
1789                 /* push value on stack */
1790                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1791                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1792               }
1793           
1794             break;
1795           }
1796         }
1797       }
1798       i++;
1799     }
1800
1801     currFunc = cfunc;
1802
1803   return pcop;
1804 }
1805
1806
1807 /*-----------------------------------------------------------------*/
1808 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1809 /*-----------------------------------------------------------------*/
1810 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1811 {
1812   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1813
1814   _TempReg_lock -= lock;
1815
1816   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1817     PCOR(pcop)->r->isFree = 1;
1818
1819     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1820   }
1821 }
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLabel(int key)
1826 {
1827
1828   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1829
1830   if(key>max_key)
1831     max_key = key;
1832
1833   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* pic16_popCopyReg - copy a pcode operator                              */
1838 /*-----------------------------------------------------------------*/
1839 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1840 {
1841   pCodeOpReg *pcor;
1842
1843   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1844   memcpy (pcor, pc, sizeof (pCodeOpReg));
1845   pcor->r->wasUsed = 1;
1846   
1847   //pcor->pcop.type = pc->pcop.type;
1848   if(pc->pcop.name) {
1849     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1850       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1851   } else
1852     pcor->pcop.name = NULL;
1853
1854   //pcor->r = pc->r;
1855   //pcor->rIdx = pc->rIdx;
1856   //pcor->r->wasUsed=1;
1857   //pcor->instance = pc->instance;
1858
1859 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1860
1861   return PCOP(pcor);
1862 }
1863
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1866 /*-----------------------------------------------------------------*/
1867 pCodeOp *pic16_popGetLit(int lit)
1868 {
1869   return pic16_newpCodeOpLit(lit);
1870 }
1871
1872 /* Allow for 12 bit literals (LFSR x, <here!>). */
1873 pCodeOp *pic16_popGetLit12(int lit)
1874 {
1875   return pic16_newpCodeOpLit12(lit);
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1880 /*-----------------------------------------------------------------*/
1881 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1882 {
1883   return pic16_newpCodeOpLit2(lit, arg2);
1884 }
1885
1886
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1891 {
1892   return pic16_newpCodeOpImmd(name, offset,index, 0);
1893 }
1894
1895
1896 /*-----------------------------------------------------------------*/
1897 /* pic16_popGet - asm operator to pcode operator conversion              */
1898 /*-----------------------------------------------------------------*/
1899 pCodeOp *pic16_popGetWithString(char *str)
1900 {
1901   pCodeOp *pcop;
1902
1903
1904   if(!str) {
1905     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1906     exit (1);
1907   }
1908
1909   pcop = pic16_newpCodeOp(str,PO_STR);
1910
1911   return pcop;
1912 }
1913
1914 /*-----------------------------------------------------------------*/
1915 /* pic16_popRegFromString -                                        */
1916 /*-----------------------------------------------------------------*/
1917 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1918 {
1919
1920   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1921   pcop->type = PO_DIR;
1922
1923   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1924   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1925
1926   if(!str)
1927     str = "BAD_STRING";
1928
1929   pcop->name = Safe_calloc(1,strlen(str)+1);
1930   strcpy(pcop->name,str);
1931
1932   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1933
1934   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1935 //  PCOR(pcop)->r->wasUsed = 1;
1936
1937   /* make sure that register doesn't exist,
1938    * and operand isn't NULL
1939    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1940   if((PCOR(pcop)->r == NULL) 
1941     && (op)
1942     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1943 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1944 //              __FUNCTION__, __LINE__, str, size, offset);
1945
1946     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1947     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1948
1949   }
1950   PCOR(pcop)->instance = offset;
1951
1952   return pcop;
1953 }
1954
1955 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1956 {
1957   pCodeOp *pcop;
1958
1959 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1960 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1961         
1962         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1963         PCOR(pcop)->rIdx = rIdx;
1964         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1965         if(!PCOR(pcop)->r)
1966                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1967                 
1968         PCOR(pcop)->r->isFree = 0;
1969         PCOR(pcop)->r->wasUsed = 1;
1970
1971         pcop->type = PCOR(pcop)->r->pc_type;
1972
1973   return pcop;
1974 }
1975
1976 /*---------------------------------------------------------------------------------*/
1977 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1978 /*                 VR 030601                                                       */
1979 /*---------------------------------------------------------------------------------*/
1980 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1981 {
1982   pCodeOpReg2 *pcop2;
1983   pCodeOp *temp;
1984   
1985         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1986
1987         /* comment the following check, so errors to throw up */
1988 //      if(!pcop2)return NULL;
1989
1990         temp = pic16_popGet(aop_dst, offset);
1991         pcop2->pcop2 = temp;
1992         
1993   return PCOP(pcop2);
1994 }
1995
1996
1997
1998 /*--------------------------------------------------------------------------------.-*/
1999 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2000 /*                  VR 030601 , adapted by Hans Dorn                                */
2001 /*--------------------------------------------------------------------------------.-*/
2002 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2003 {
2004   pCodeOpReg2 *pcop2;
2005  
2006         pcop2 = (pCodeOpReg2 *)src;
2007         pcop2->pcop2 = dst;
2008         
2009         return PCOP(pcop2);
2010 }
2011
2012
2013
2014 /*---------------------------------------------------------------------------------*/
2015 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2016 /*                     movff instruction                                           */
2017 /*---------------------------------------------------------------------------------*/
2018 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2019 {
2020   pCodeOpReg2 *pcop2;
2021
2022         if(!noalloc) {
2023                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2024                 pcop2->pcop2 = pic16_popCopyReg(dst);
2025         } else {
2026                 /* the pCodeOp may be already allocated */
2027                 pcop2 = (pCodeOpReg2 *)(src);
2028                 pcop2->pcop2 = (pCodeOp *)(dst);
2029         }
2030
2031   return PCOP(pcop2);
2032 }
2033
2034
2035 /*-----------------------------------------------------------------*/
2036 /* pic16_popGet - asm operator to pcode operator conversion              */
2037 /*-----------------------------------------------------------------*/
2038 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2039 {
2040 //  char *s = buffer ;
2041 //  char *rs;
2042   pCodeOp *pcop;
2043
2044         FENTRY2;
2045                 /* offset is greater than
2046                  * size then zero */
2047
2048 //    if (offset > (aop->size - 1) &&
2049 //        aop->type != AOP_LIT)
2050 //      return NULL;  //zero;
2051
2052     /* depending on type */
2053     switch (aop->type) {
2054                 case AOP_R0:
2055                 case AOP_R1:
2056                 case AOP_DPTR:
2057                 case AOP_DPTR2:
2058                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2059                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2060                         assert( 0 );
2061                         return NULL;
2062
2063                 case AOP_FSR0:
2064                 case AOP_FSR2:
2065                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2066                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2067                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2068                         PCOR(pcop)->r->wasUsed = 1;
2069                         PCOR(pcop)->r->isFree = 0;
2070       
2071                         PCOR(pcop)->instance = offset;
2072                         pcop->type = PCOR(pcop)->r->pc_type;
2073                         return (pcop);
2074
2075                 case AOP_IMMD:
2076                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2077                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2078
2079                 case AOP_STA:
2080                         /* pCodeOp is already allocated from aopForSym */
2081                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2082                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2083                         return (pcop);
2084       
2085                 case AOP_ACC:
2086                         {
2087                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2088
2089                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2090
2091                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2092         
2093                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2094                                 PCOR(pcop)->rIdx = rIdx;
2095                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2096                                 PCOR(pcop)->r->wasUsed=1;
2097                                 PCOR(pcop)->r->isFree=0;
2098
2099                                 PCOR(pcop)->instance = offset;
2100                                 pcop->type = PCOR(pcop)->r->pc_type;
2101 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2102                                 return pcop;
2103
2104
2105 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2106 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2107
2108 //      assert( 0 );
2109                         }
2110         
2111     case AOP_DIR:
2112       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2113       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2114         
2115 #if 0
2116     case AOP_PAGED:
2117       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2118       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2119 #endif
2120
2121     case AOP_REG:
2122       {
2123         int rIdx;
2124         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2125         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2126
2127         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2128         
2129         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2130 //      pcop->type = PO_GPR_REGISTER;
2131         PCOR(pcop)->rIdx = rIdx;
2132         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2133         PCOR(pcop)->r->wasUsed=1;
2134         PCOR(pcop)->r->isFree=0;
2135
2136         PCOR(pcop)->instance = offset;
2137         pcop->type = PCOR(pcop)->r->pc_type;
2138         
2139         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2140 //      rs = aop->aopu.aop_reg[offset]->name;
2141 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2142         return pcop;
2143       }
2144
2145     case AOP_CRY:
2146         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2147
2148       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2149       PCOR(pcop)->instance = offset;
2150       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2151       //if(PCOR(pcop)->r == NULL)
2152       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2153       return pcop;
2154         
2155     case AOP_LIT:
2156         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2157       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2158
2159     case AOP_STR:
2160       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2161       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2162
2163       /*
2164       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2165       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2166       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2167       pcop->type = PCOR(pcop)->r->pc_type;
2168       pcop->name = PCOR(pcop)->r->name;
2169
2170       return pcop;
2171       */
2172
2173     case AOP_PCODE:
2174       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2175                           __LINE__, 
2176                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2177       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2178       switch( aop->aopu.pcop->type ) {
2179         case PO_DIR: PCOR(pcop)->instance += offset; break;
2180         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2181         case PO_WREG:
2182             assert (offset==0);
2183             break;
2184         default:
2185           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2186           assert( 0 );  /* should never reach here */;
2187       }
2188       return pcop;
2189     }
2190
2191     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2192            "pic16_popGet got unsupported aop->type");
2193     exit(0);
2194 }
2195 /*-----------------------------------------------------------------*/
2196 /* pic16_aopPut - puts a string for a aop                                */
2197 /*-----------------------------------------------------------------*/
2198 void pic16_aopPut (asmop *aop, char *s, int offset)
2199 {
2200     char *d = buffer ;
2201     symbol *lbl ;
2202
2203     return;
2204
2205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2206
2207     if (aop->size && offset > ( aop->size - 1)) {
2208         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2209                "pic16_aopPut got offset > aop->size");
2210         exit(0);
2211     }
2212
2213     /* will assign value to value */
2214     /* depending on where it is ofcourse */
2215     switch (aop->type) {
2216     case AOP_DIR:
2217       if (offset) {
2218         sprintf(d,"(%s + %d)",
2219                 aop->aopu.aop_dir,offset);
2220         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2221
2222       } else
2223             sprintf(d,"%s",aop->aopu.aop_dir);
2224         
2225         if (strcmp(d,s)) {
2226           DEBUGpic16_emitcode(";","%d",__LINE__);
2227           if(strcmp(s,"W"))
2228             pic16_emitcode("movf","%s,w",s);
2229           pic16_emitcode("movwf","%s",d);
2230
2231           if(strcmp(s,"W")) {
2232             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2233             if(offset >= aop->size) {
2234               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2235               break;
2236             } else
2237               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2238           }
2239
2240           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2241
2242
2243         }
2244         break;
2245         
2246     case AOP_REG:
2247       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2248         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2249           /*
2250             if (*s == '@'           ||
2251                 strcmp(s,"r0") == 0 ||
2252                 strcmp(s,"r1") == 0 ||
2253                 strcmp(s,"r2") == 0 ||
2254                 strcmp(s,"r3") == 0 ||
2255                 strcmp(s,"r4") == 0 ||
2256                 strcmp(s,"r5") == 0 ||
2257                 strcmp(s,"r6") == 0 || 
2258                 strcmp(s,"r7") == 0 )
2259                 pic16_emitcode("mov","%s,%s  ; %d",
2260                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2261             else
2262           */
2263
2264           if(strcmp(s,"W")==0 )
2265             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2266
2267           pic16_emitcode("movwf","%s",
2268                    aop->aopu.aop_reg[offset]->name);
2269
2270           if(strcmp(s,zero)==0) {
2271             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2272
2273           } else if(strcmp(s,"W")==0) {
2274             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2275             pcop->type = PO_GPR_REGISTER;
2276
2277             PCOR(pcop)->rIdx = -1;
2278             PCOR(pcop)->r = NULL;
2279
2280             DEBUGpic16_emitcode(";","%d",__LINE__);
2281             pcop->name = Safe_strdup(s);
2282             pic16_emitpcode(POC_MOVFW,pcop);
2283             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2284           } else if(strcmp(s,one)==0) {
2285             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2286             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2287           } else {
2288             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2289           }
2290         }
2291         break;
2292         
2293     case AOP_DPTR:
2294     case AOP_DPTR2:
2295     
2296     if (aop->type == AOP_DPTR2)
2297     {
2298         genSetDPTR(1);
2299     }
2300     
2301         if (aop->code) {
2302             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2303                    "pic16_aopPut writting to code space");
2304             exit(0);
2305         }
2306         
2307         while (offset > aop->coff) {
2308             aop->coff++;
2309             pic16_emitcode ("inc","dptr");
2310         }
2311         
2312         while (offset < aop->coff) {
2313             aop->coff-- ;
2314             pic16_emitcode("lcall","__decdptr");
2315         }
2316         
2317         aop->coff = offset;
2318         
2319         /* if not in accumulater */
2320         MOVA(s);        
2321         
2322         pic16_emitcode ("movx","@dptr,a");
2323         
2324     if (aop->type == AOP_DPTR2)
2325     {
2326         genSetDPTR(0);
2327     }
2328         break;
2329         
2330     case AOP_R0:
2331     case AOP_R1:
2332         while (offset > aop->coff) {
2333             aop->coff++;
2334             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2335         }
2336         while (offset < aop->coff) {
2337             aop->coff-- ;
2338             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2339         }
2340         aop->coff = offset;
2341         
2342         if (aop->paged) {
2343             MOVA(s);           
2344             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2345             
2346         } else
2347             if (*s == '@') {
2348                 MOVA(s);
2349                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2350             } else
2351                 if (strcmp(s,"r0") == 0 ||
2352                     strcmp(s,"r1") == 0 ||
2353                     strcmp(s,"r2") == 0 ||
2354                     strcmp(s,"r3") == 0 ||
2355                     strcmp(s,"r4") == 0 ||
2356                     strcmp(s,"r5") == 0 ||
2357                     strcmp(s,"r6") == 0 || 
2358                     strcmp(s,"r7") == 0 ) {
2359                     char buffer[10];
2360                     sprintf(buffer,"a%s",s);
2361                     pic16_emitcode("mov","@%s,%s",
2362                              aop->aopu.aop_ptr->name,buffer);
2363                 } else
2364                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2365         
2366         break;
2367         
2368     case AOP_STK:
2369         if (strcmp(s,"a") == 0)
2370             pic16_emitcode("push","acc");
2371         else
2372             pic16_emitcode("push","%s",s);
2373         
2374         break;
2375         
2376     case AOP_CRY:
2377         /* if bit variable */
2378         if (!aop->aopu.aop_dir) {
2379             pic16_emitcode("clr","a");
2380             pic16_emitcode("rlc","a");
2381         } else {
2382             if (s == zero) 
2383                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2384             else
2385                 if (s == one)
2386                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2387                 else
2388                     if (!strcmp(s,"c"))
2389                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2390                     else {
2391                         lbl = newiTempLabel(NULL);
2392                         
2393                         if (strcmp(s,"a")) {
2394                             MOVA(s);
2395                         }
2396                         pic16_emitcode("clr","c");
2397                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2398                         pic16_emitcode("cpl","c");
2399                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2400                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2401                     }
2402         }
2403         break;
2404         
2405     case AOP_STR:
2406         aop->coff = offset;
2407         if (strcmp(aop->aopu.aop_str[offset],s))
2408             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2409         break;
2410         
2411     case AOP_ACC:
2412         aop->coff = offset;
2413         if (!offset && (strcmp(s,"acc") == 0))
2414             break;
2415         
2416         if (strcmp(aop->aopu.aop_str[offset],s))
2417             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2418         break;
2419
2420     default :
2421         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2422 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2423 //             "pic16_aopPut got unsupported aop->type");
2424 //      exit(0);    
2425     }    
2426
2427 }
2428
2429 /*-----------------------------------------------------------------*/
2430 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2431 /*-----------------------------------------------------------------*/
2432 void pic16_mov2w (asmop *aop, int offset)
2433 {
2434   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2435
2436   if(is_LitAOp(aop))
2437     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2438   else
2439     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2440 }
2441
2442 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2443 {
2444   if(is_LitAOp(src)) {
2445     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2446     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2447   } else {
2448     if(pic16_sameRegsOfs(src, dst, offset))return;
2449     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2450                       pic16_popGet(dst, offset)));
2451   }
2452 }
2453
2454 static void pic16_movLit2f(pCodeOp *pc, int lit)
2455 {
2456   if (0 == (lit & 0x00ff))
2457   {
2458     pic16_emitpcode (POC_CLRF, pc);
2459   } else if (0xff == (lit & 0x00ff))
2460   {
2461     pic16_emitpcode (POC_SETF, pc);
2462   } else {
2463     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2464     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2465   }
2466 }
2467
2468 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2469 {
2470   if(is_LitAOp(src)) {
2471     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2472     pic16_emitpcode(POC_MOVWF, dst);
2473   } else {
2474     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2475   }
2476 }
2477
2478 void pic16_testStackOverflow(void)
2479 {
2480 #define GSTACK_TEST_NAME        "_gstack_test"
2481
2482   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2483   
2484   {
2485     symbol *sym;
2486
2487       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2488       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2489 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2490       checkAddSym(&externs, sym);
2491   }
2492
2493 }
2494
2495 /* push pcop into stack */
2496 void pic16_pushpCodeOp(pCodeOp *pcop)
2497 {
2498 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2499   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2500   if(pic16_options.gstack)
2501     pic16_testStackOverflow();
2502     
2503 }
2504
2505 /* pop pcop from stack */
2506 void pic16_poppCodeOp(pCodeOp *pcop)
2507 {
2508   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2509   if(pic16_options.gstack)
2510     pic16_testStackOverflow();
2511 }
2512
2513
2514 /*-----------------------------------------------------------------*/
2515 /* pushw - pushes wreg to stack                                    */
2516 /*-----------------------------------------------------------------*/
2517 void pushw(void)
2518 {
2519   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2520   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2521   if(pic16_options.gstack)
2522     pic16_testStackOverflow();
2523 }
2524
2525                 
2526 /*-----------------------------------------------------------------*/
2527 /* pushaop - pushes aop to stack                                   */
2528 /*-----------------------------------------------------------------*/
2529 void pushaop(asmop *aop, int offset)
2530 {
2531   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2532
2533   if(_G.resDirect)return;
2534   
2535   if(is_LitAOp(aop)) {
2536     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2537     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2538   } else {
2539     pic16_emitpcode(POC_MOVFF,
2540       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2541   }
2542
2543   if(pic16_options.gstack)
2544     pic16_testStackOverflow();
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* popaop - pops aop from stack                                    */
2549 /*-----------------------------------------------------------------*/
2550 void popaop(asmop *aop, int offset)
2551 {
2552   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2553   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2554   if(pic16_options.gstack)
2555     pic16_testStackOverflow();
2556 }
2557
2558 void popaopidx(asmop *aop, int offset, int index)
2559 {
2560   int ofs=1;
2561
2562     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2563
2564     if(STACK_MODEL_LARGE)ofs++;
2565
2566     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2567     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2568     if(pic16_options.gstack)
2569       pic16_testStackOverflow();
2570 }
2571
2572 #if !(USE_GENERIC_SIGNED_SHIFT)
2573 /*-----------------------------------------------------------------*/
2574 /* reAdjustPreg - points a register back to where it should        */
2575 /*-----------------------------------------------------------------*/
2576 static void reAdjustPreg (asmop *aop)
2577 {
2578     int size ;
2579
2580     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2581     aop->coff = 0;
2582     if ((size = aop->size) <= 1)
2583         return ;
2584     size-- ;
2585     switch (aop->type) {
2586         case AOP_R0 :
2587         case AOP_R1 :
2588             while (size--)
2589                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2590             break;          
2591         case AOP_DPTR :
2592         case AOP_DPTR2:
2593             if (aop->type == AOP_DPTR2)
2594             {
2595                 genSetDPTR(1);
2596             } 
2597             while (size--)
2598             {
2599                 pic16_emitcode("lcall","__decdptr");
2600             }
2601                 
2602             if (aop->type == AOP_DPTR2)
2603             {
2604                 genSetDPTR(0);
2605             }                
2606             break;  
2607
2608     }   
2609
2610 }
2611 #endif
2612
2613 #if 0
2614 /*-----------------------------------------------------------------*/
2615 /* opIsGptr: returns non-zero if the passed operand is             */   
2616 /* a generic pointer type.                                         */
2617 /*-----------------------------------------------------------------*/ 
2618 static int opIsGptr(operand *op)
2619 {
2620     sym_link *type = operandType(op);
2621     
2622     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2623     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2624     {
2625         return 1;
2626     }
2627     return 0;        
2628 }
2629 #endif
2630
2631 /*-----------------------------------------------------------------*/
2632 /* pic16_getDataSize - get the operand data size                         */
2633 /*-----------------------------------------------------------------*/
2634 int pic16_getDataSize(operand *op)
2635 {
2636     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2637
2638
2639     return AOP_SIZE(op);
2640
2641     // tsd- in the pic port, the genptr size is 1, so this code here
2642     // fails. ( in the 8051 port, the size was 4).
2643 #if 0
2644     int size;
2645     size = AOP_SIZE(op);
2646     if (size == GPTRSIZE)
2647     {
2648         sym_link *type = operandType(op);
2649         if (IS_GENPTR(type))
2650         {
2651             /* generic pointer; arithmetic operations
2652              * should ignore the high byte (pointer type).
2653              */
2654             size--;
2655     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2656         }
2657     }
2658     return size;
2659 #endif
2660 }
2661
2662 /*-----------------------------------------------------------------*/
2663 /* pic16_outAcc - output Acc                                             */
2664 /*-----------------------------------------------------------------*/
2665 void pic16_outAcc(operand *result)
2666 {
2667   int size,offset;
2668   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2669   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2670
2671
2672   size = pic16_getDataSize(result);
2673   if(size){
2674     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2675     size--;
2676     offset = 1;
2677     /* unsigned or positive */
2678     while(size--)
2679       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2680   }
2681
2682 }
2683
2684 /*-----------------------------------------------------------------*/
2685 /* pic16_outBitC - output a bit C                                  */
2686 /*                 Move to result the value of Carry flag -- VR    */
2687 /*-----------------------------------------------------------------*/
2688 void pic16_outBitC(operand *result)
2689 {
2690   int i;
2691
2692     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2693
2694     /* if the result is bit */
2695     if (AOP_TYPE(result) == AOP_CRY) {
2696         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2697         pic16_aopPut(AOP(result),"c",0);
2698     } else {
2699
2700         i = AOP_SIZE(result);
2701         while(i--) {
2702                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2703         }
2704         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2705     }
2706 }
2707
2708 /*-----------------------------------------------------------------*/
2709 /* pic16_outBitOp - output a bit from Op                           */
2710 /*                 Move to result the value of set/clr op -- VR    */
2711 /*-----------------------------------------------------------------*/
2712 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2713 {
2714   int i;
2715
2716     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2717
2718     /* if the result is bit */
2719     if (AOP_TYPE(result) == AOP_CRY) {
2720         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2721         pic16_aopPut(AOP(result),"c",0);
2722     } else {
2723
2724         i = AOP_SIZE(result);
2725         while(i--) {
2726                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2727         }
2728         pic16_emitpcode(POC_RRCF, pcop);          
2729         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2730     }
2731 }
2732
2733 /*-----------------------------------------------------------------*/
2734 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2735 /*-----------------------------------------------------------------*/
2736 void pic16_toBoolean(operand *oper)
2737 {
2738     int size = AOP_SIZE(oper) - 1;
2739     int offset = 1;
2740
2741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2742
2743     if ( AOP_TYPE(oper) != AOP_ACC) {
2744       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2745     }
2746     while (size--) {
2747       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2748     }
2749 }
2750
2751 /*-----------------------------------------------------------------*/
2752 /* genUminusFloat - unary minus for floating points                */
2753 /*-----------------------------------------------------------------*/
2754 static void genUminusFloat(operand *op,operand *result)
2755 {
2756   int size ,offset =0 ;
2757   
2758     FENTRY;
2759     /* for this we just need to flip the 
2760     first it then copy the rest in place */
2761     size = AOP_SIZE(op);
2762     assert( size == AOP_SIZE(result) );
2763
2764     while(size--) {
2765       pic16_mov2f(AOP(result), AOP(op), offset);
2766       offset++;
2767     }
2768     
2769     /* toggle the MSB's highest bit */
2770     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2771 }
2772
2773 /*-----------------------------------------------------------------*/
2774 /* genUminus - unary minus code generation                         */
2775 /*-----------------------------------------------------------------*/
2776 static void genUminus (iCode *ic)
2777 {
2778   int size, i;
2779   sym_link *optype, *rtype;
2780   symbol *label;
2781   int needLabel=0;
2782
2783     FENTRY;     
2784     
2785     /* assign asmops */
2786     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2787     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2788
2789     /* if both in bit space then special case */
2790     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2791       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2792         
2793         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2794         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2795         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2796         goto release; 
2797     } 
2798
2799     optype = operandType(IC_LEFT(ic));
2800     rtype = operandType(IC_RESULT(ic));
2801
2802
2803     /* if float then do float stuff */
2804     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2805       if(IS_FIXED(optype))
2806         debugf("implement fixed16x16 type\n", 0);
2807         
2808         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2809         goto release;
2810     }
2811
2812     /* otherwise subtract from zero by taking the 2's complement */
2813     size = AOP_SIZE(IC_LEFT(ic));
2814     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2815     label = newiTempLabel ( NULL );
2816     
2817     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2818       for (i=size-1; i > 0; i--) {
2819         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2820       } // for
2821       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2822       for (i=1; i < size; i++) {
2823         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2824         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2825       } // for
2826     } else {
2827       for (i=size-1; i >= 0; i--) {
2828         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2829         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2830       } // for
2831       if (size > 1) {
2832         for (i=0; i < size-2; i++) {
2833           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2834           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2835         } // for
2836         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2837       } // if
2838       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2839     }
2840     if (needLabel)
2841       pic16_emitpLabel (label->key);
2842
2843 release:
2844     /* release the aops */
2845     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2846     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2847 }
2848
2849 #if 0
2850 /*-----------------------------------------------------------------*/
2851 /* saveRegisters - will look for a call and save the registers     */
2852 /*-----------------------------------------------------------------*/
2853 static void saveRegisters(iCode *lic) 
2854 {
2855     int i;
2856     iCode *ic;
2857     bitVect *rsave;
2858     sym_link *dtype;
2859
2860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2861     /* look for call */
2862     for (ic = lic ; ic ; ic = ic->next) 
2863         if (ic->op == CALL || ic->op == PCALL)
2864             break;
2865
2866     if (!ic) {
2867         fprintf(stderr,"found parameter push with no function call\n");
2868         return ;
2869     }
2870
2871     /* if the registers have been saved already then
2872     do nothing */
2873     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2874         return ;
2875
2876     /* find the registers in use at this time 
2877     and push them away to safety */
2878     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2879                           ic->rUsed);
2880
2881     ic->regsSaved = 1;
2882     if (options.useXstack) {
2883         if (bitVectBitValue(rsave,R0_IDX))
2884             pic16_emitcode("mov","b,r0");
2885         pic16_emitcode("mov","r0,%s",spname);
2886         for (i = 0 ; i < pic16_nRegs ; i++) {
2887             if (bitVectBitValue(rsave,i)) {
2888                 if (i == R0_IDX)
2889                     pic16_emitcode("mov","a,b");
2890                 else
2891                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2892                 pic16_emitcode("movx","@r0,a");
2893                 pic16_emitcode("inc","r0");
2894             }
2895         }
2896         pic16_emitcode("mov","%s,r0",spname);
2897         if (bitVectBitValue(rsave,R0_IDX))
2898             pic16_emitcode("mov","r0,b");           
2899     }// else
2900     //for (i = 0 ; i < pic16_nRegs ; i++) {
2901     //    if (bitVectBitValue(rsave,i))
2902     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2903     //}
2904
2905     dtype = operandType(IC_LEFT(ic));
2906     if (currFunc && dtype && 
2907         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2908         IFFUNC_ISISR(currFunc->type) &&
2909         !ic->bankSaved) 
2910
2911         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2912
2913 }
2914 /*-----------------------------------------------------------------*/
2915 /* unsaveRegisters - pop the pushed registers                      */
2916 /*-----------------------------------------------------------------*/
2917 static void unsaveRegisters (iCode *ic)
2918 {
2919     int i;
2920     bitVect *rsave;
2921
2922     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2923     /* find the registers in use at this time 
2924     and push them away to safety */
2925     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2926                           ic->rUsed);
2927     
2928     if (options.useXstack) {
2929         pic16_emitcode("mov","r0,%s",spname);   
2930         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2931             if (bitVectBitValue(rsave,i)) {
2932                 pic16_emitcode("dec","r0");
2933                 pic16_emitcode("movx","a,@r0");
2934                 if (i == R0_IDX)
2935                     pic16_emitcode("mov","b,a");
2936                 else
2937                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2938             }       
2939
2940         }
2941         pic16_emitcode("mov","%s,r0",spname);
2942         if (bitVectBitValue(rsave,R0_IDX))
2943             pic16_emitcode("mov","r0,b");
2944     } //else
2945     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2946     //    if (bitVectBitValue(rsave,i))
2947     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2948     //}
2949
2950 }  
2951 #endif
2952
2953 #if 0  // patch 14
2954 /*-----------------------------------------------------------------*/
2955 /* pushSide -                                                      */
2956 /*-----------------------------------------------------------------*/
2957 static void pushSide(operand * oper, int size)
2958 {
2959         int offset = 0;
2960     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2961         while (size--) {
2962                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2963                 if (AOP_TYPE(oper) != AOP_REG &&
2964                     AOP_TYPE(oper) != AOP_DIR &&
2965                     strcmp(l,"a") ) {
2966                         pic16_emitcode("mov","a,%s",l);
2967                         pic16_emitcode("push","acc");
2968                 } else
2969                         pic16_emitcode("push","%s",l);
2970         }
2971 }
2972 #endif // patch 14
2973
2974 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2975 {
2976   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2977     pic16_emitpcode(POC_MOVFW, src);
2978     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2979   } else {
2980     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2981         src, pic16_popGet(AOP(op), offset)));
2982   }
2983 }
2984
2985
2986 /*-----------------------------------------------------------------*/
2987 /* assignResultValue - assign results to oper, rescall==1 is       */
2988 /*                     called from genCall() or genPcall()         */
2989 /*-----------------------------------------------------------------*/
2990 static void assignResultValue(operand * oper, int rescall)
2991 {
2992   int size = AOP_SIZE(oper);
2993   int offset=0;
2994   
2995     FENTRY2;
2996 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2997     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2998
2999     if(rescall) {
3000       /* assign result from a call/pcall function() */
3001                 
3002       /* function results are stored in a special order,
3003        * see top of file with Function return policy, or manual */
3004
3005       if(size <= 4) {
3006         /* 8-bits, result in WREG */
3007         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3008                         
3009         if(size>1) {
3010           /* 16-bits, result in PRODL:WREG */
3011           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3012         }
3013                         
3014         if(size>2) {
3015           /* 24-bits, result in PRODH:PRODL:WREG */
3016           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3017         }
3018                         
3019         if(size>3) {
3020           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3021           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3022         }
3023       
3024       } else {
3025         /* >32-bits, result on stack, and FSR0 points to beginning.
3026          * Fix stack when done */
3027         /* FIXME FIXME */
3028 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3029         while (size--) {
3030 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3031 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3032                 
3033           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3034           GpsuedoStkPtr++;
3035         }
3036                         
3037         /* fix stack */
3038         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3039         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3040         if(STACK_MODEL_LARGE) {
3041           emitSKPNC;
3042           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3043         }
3044       }                 
3045     } else {
3046       int areg = 0;             /* matching argument register */
3047       
3048 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3049       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3050
3051
3052       /* its called from genReceive (probably) -- VR */
3053       /* I hope this code will not be called from somewhere else in the future! 
3054        * We manually set the pseudo stack pointer in genReceive. - dw
3055        */
3056       if(!GpsuedoStkPtr && _G.useWreg) {
3057 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3058
3059         /* The last byte in the assignment is in W */
3060         if(areg <= GpsuedoStkPtr) {
3061           size--;
3062           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3063           offset++;
3064 //          debugf("receive from WREG\n", 0);
3065         }
3066         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3067       }
3068 //      GpsuedoStkPtr++;
3069       _G.stack_lat = AOP_SIZE(oper)-1;
3070
3071       while (size) {
3072         size--;
3073         GpsuedoStkPtr++;
3074         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3075 //        debugf("receive from STACK\n", 0);
3076         offset++;
3077       }
3078     }
3079 }
3080
3081
3082 /*-----------------------------------------------------------------*/
3083 /* genIpush - generate code for pushing this gets a little complex */
3084 /*-----------------------------------------------------------------*/
3085 static void genIpush (iCode *ic)
3086 {
3087 //  int size, offset=0;
3088
3089   FENTRY;
3090   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3091
3092   if(ic->parmPush) {
3093     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3094
3095     /* send to stack as normal */
3096     addSet(&_G.sendSet,ic);
3097 //    addSetHead(&_G.sendSet,ic);
3098     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3099   }
3100
3101         
3102 #if 0
3103     int size, offset = 0 ;
3104     char *l;
3105
3106
3107     /* if this is not a parm push : ie. it is spill push 
3108     and spill push is always done on the local stack */
3109     if (!ic->parmPush) {
3110
3111         /* and the item is spilt then do nothing */
3112         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3113             return ;
3114
3115         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3116         size = AOP_SIZE(IC_LEFT(ic));
3117         /* push it on the stack */
3118         while(size--) {
3119             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3120             if (*l == '#') {
3121                 MOVA(l);
3122                 l = "acc";
3123             }
3124             pic16_emitcode("push","%s",l);
3125         }
3126         return ;        
3127     }
3128
3129     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3130 #endif
3131 }
3132
3133 /*-----------------------------------------------------------------*/
3134 /* genIpop - recover the registers: can happen only for spilling   */
3135 /*-----------------------------------------------------------------*/
3136 static void genIpop (iCode *ic)
3137 {
3138   FENTRY;
3139   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3140 #if 0
3141     int size,offset ;
3142
3143
3144     /* if the temp was not pushed then */
3145     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3146         return ;
3147
3148     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3149     size = AOP_SIZE(IC_LEFT(ic));
3150     offset = (size-1);
3151     while (size--) 
3152         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3153                                    FALSE,TRUE));
3154
3155     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3156 #endif
3157 }
3158
3159 #if 0
3160 /*-----------------------------------------------------------------*/
3161 /* unsaverbank - restores the resgister bank from stack            */
3162 /*-----------------------------------------------------------------*/
3163 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3164 {
3165   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3166 #if 0
3167     int i;
3168     asmop *aop ;
3169     regs *r = NULL;
3170
3171     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3172     if (popPsw) {
3173         if (options.useXstack) {
3174             aop = newAsmop(0);
3175             r = getFreePtr(ic,&aop,FALSE);
3176             
3177             
3178             pic16_emitcode("mov","%s,_spx",r->name);
3179             pic16_emitcode("movx","a,@%s",r->name);
3180             pic16_emitcode("mov","psw,a");
3181             pic16_emitcode("dec","%s",r->name);
3182             
3183         }else
3184             pic16_emitcode ("pop","psw");
3185     }
3186
3187     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3188         if (options.useXstack) {       
3189             pic16_emitcode("movx","a,@%s",r->name);
3190             //pic16_emitcode("mov","(%s+%d),a",
3191             //       regspic16[i].base,8*bank+regspic16[i].offset);
3192             pic16_emitcode("dec","%s",r->name);
3193
3194         } else 
3195           pic16_emitcode("pop",""); //"(%s+%d)",
3196         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3197     }
3198
3199     if (options.useXstack) {
3200
3201         pic16_emitcode("mov","_spx,%s",r->name);
3202         pic16_freeAsmop(NULL,aop,ic,TRUE);
3203
3204     }
3205 #endif 
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* saverbank - saves an entire register bank on the stack          */
3210 /*-----------------------------------------------------------------*/
3211 static void saverbank (int bank, iCode *ic, bool pushPsw)
3212 {
3213   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3214 #if 0
3215     int i;
3216     asmop *aop ;
3217     regs *r = NULL;
3218
3219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3220     if (options.useXstack) {
3221
3222         aop = newAsmop(0);
3223         r = getFreePtr(ic,&aop,FALSE);  
3224         pic16_emitcode("mov","%s,_spx",r->name);
3225
3226     }
3227
3228     for (i = 0 ; i < pic16_nRegs ;i++) {
3229         if (options.useXstack) {
3230             pic16_emitcode("inc","%s",r->name);
3231             //pic16_emitcode("mov","a,(%s+%d)",
3232             //         regspic16[i].base,8*bank+regspic16[i].offset);
3233             pic16_emitcode("movx","@%s,a",r->name);           
3234         } else 
3235           pic16_emitcode("push","");// "(%s+%d)",
3236                      //regspic16[i].base,8*bank+regspic16[i].offset);
3237     }
3238     
3239     if (pushPsw) {
3240         if (options.useXstack) {
3241             pic16_emitcode("mov","a,psw");
3242             pic16_emitcode("movx","@%s,a",r->name);     
3243             pic16_emitcode("inc","%s",r->name);
3244             pic16_emitcode("mov","_spx,%s",r->name);       
3245             pic16_freeAsmop (NULL,aop,ic,TRUE);
3246             
3247         } else
3248             pic16_emitcode("push","psw");
3249         
3250         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3251     }
3252     ic->bankSaved = 1;
3253 #endif
3254 }
3255 #endif  /* 0 */
3256
3257
3258 static int wparamCmp(void *p1, void *p2)
3259 {
3260   return (!strcmp((char *)p1, (char *)p2));
3261 }
3262
3263 int inWparamList(char *s)
3264 {
3265   return isinSetWith(wparamList, s, wparamCmp);
3266
3267
3268
3269 /*-----------------------------------------------------------------*/
3270 /* genCall - generates a call statement                            */
3271 /*-----------------------------------------------------------------*/
3272 static void genCall (iCode *ic)
3273 {
3274   sym_link *ftype;   
3275   int stackParms=0;
3276   int use_wreg=0;
3277   int inwparam=0;
3278   char *fname;
3279   
3280     FENTRY;
3281
3282     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3283     /* if caller saves & we have not saved then */
3284 //    if (!ic->regsSaved)
3285 //      saveRegisters(ic);
3286
3287         /* initialise stackParms for IPUSH pushes */
3288 //      stackParms = psuedoStkPtr;
3289 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3290     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3291     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3292
3293 #if 0
3294     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3295 #endif
3296
3297     /* if send set is not empty the assign */
3298     if (_G.sendSet) {
3299       iCode *sic;
3300       int psuedoStkPtr=-1; 
3301       int firstTimeThruLoop = 1;
3302
3303
3304         /* reverse sendSet if function is not reentrant */
3305         if(!IFFUNC_ISREENT(ftype))
3306           _G.sendSet = reverseSet(_G.sendSet);
3307
3308         /* First figure how many parameters are getting passed */
3309         stackParms = 0;
3310         use_wreg = 0;
3311         
3312         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3313           int size;
3314 //          int offset = 0;
3315
3316             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3317             size = AOP_SIZE(IC_LEFT(sic));
3318
3319             stackParms += size;
3320
3321             /* pass the last byte through WREG */
3322             if(inwparam) {
3323
3324               while (size--) {
3325                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3326                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3327                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3328
3329                 if(!firstTimeThruLoop) {
3330                   /* If this is not the first time we've been through the loop
3331                    * then we need to save the parameter in a temporary
3332                    * register. The last byte of the last parameter is
3333                    * passed in W. */
3334
3335                   pushw();
3336 //                  --psuedoStkPtr;             // sanity check
3337                   use_wreg = 1;
3338                 }
3339                 
3340                 firstTimeThruLoop=0;
3341
3342                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3343
3344 //                offset++;
3345               }
3346             } else {
3347               /* all arguments are passed via stack */
3348               use_wreg = 0;
3349
3350               while (size--) {
3351                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3352                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3353                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3354
3355 //                pushaop(AOP(IC_LEFT(sic)), size);
3356                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3357                                 
3358                 if(!_G.resDirect)
3359                   pushw();
3360               }
3361             }
3362
3363             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3364           }
3365
3366           if(inwparam) {
3367             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3368               pushw();  /* save last parameter to stack if functions has varargs */
3369               use_wreg = 0;
3370             } else
3371               use_wreg = 1;
3372           } else use_wreg = 0;
3373
3374           _G.stackRegSet = _G.sendSet;
3375           _G.sendSet = NULL;
3376     }
3377
3378     /* make the call */
3379     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3380
3381     GpsuedoStkPtr=0;
3382     
3383     /* if we need to assign a result value */
3384     if ((IS_ITEMP(IC_RESULT(ic))
3385           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3386               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3387         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3388
3389       _G.accInUse++;
3390       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3391       _G.accInUse--;
3392
3393       assignResultValue(IC_RESULT(ic), 1);
3394
3395       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3396                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3397                 
3398       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3399     }
3400
3401     if(!stackParms && ic->parmBytes) {
3402       stackParms = ic->parmBytes;
3403     }
3404       
3405     stackParms -= use_wreg;
3406     
3407     if(stackParms>0) {
3408       if(stackParms == 1) {
3409         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3410       } else {
3411         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3412         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3413       }
3414       if(STACK_MODEL_LARGE) {
3415         emitSKPNC;
3416         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3417       }
3418     }
3419
3420 #if 0
3421     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3422 #endif
3423
3424     /* adjust the stack for parameters if required */
3425 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3426
3427 #if 0
3428       /* if register bank was saved then pop them */
3429       if (ic->bankSaved)
3430         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3431
3432       /* if we hade saved some registers then unsave them */
3433       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3434         unsaveRegisters (ic);
3435 #endif
3436 }
3437
3438
3439
3440 /*-----------------------------------------------------------------*/
3441 /* genPcall - generates a call by pointer statement                */
3442 /*            new version, created from genCall - HJD              */
3443 /*-----------------------------------------------------------------*/
3444 static void genPcall (iCode *ic)
3445 {
3446   sym_link *fntype;
3447   int stackParms=0;
3448   symbol *retlbl = newiTempLabel(NULL);
3449   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3450   
3451     FENTRY;
3452
3453     fntype = operandType( IC_LEFT(ic) )->next;
3454
3455     /* if send set is not empty the assign */
3456     if (_G.sendSet) {
3457       iCode *sic;
3458       int psuedoStkPtr=-1; 
3459
3460       /* reverse sendSet if function is not reentrant */
3461       if(!IFFUNC_ISREENT(fntype))
3462         _G.sendSet = reverseSet(_G.sendSet);
3463
3464       stackParms = 0;
3465       
3466       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3467         int size;
3468
3469           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3470           size = AOP_SIZE(IC_LEFT(sic));
3471           stackParms += size;
3472
3473           /* all parameters are passed via stack, since WREG is clobbered
3474            * by the calling sequence */
3475           while (size--) {
3476             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3477             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3478             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3479
3480             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3481             pushw();
3482           }
3483
3484           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3485       }
3486
3487       _G.stackRegSet = _G.sendSet;
3488       _G.sendSet = NULL;
3489     }
3490
3491     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3492
3493     // push return address
3494     // push $ on return stack, then replace with retlbl
3495
3496     /* Thanks to Thorsten Klose for pointing out that the following
3497      * snippet should be interrupt safe */
3498     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3499     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3500
3501     pic16_emitpcodeNULLop(POC_PUSH);
3502
3503     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3504     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3505     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3506     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3507     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3508     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3509
3510
3511     /* restore interrupt control register */
3512     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3513     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3514
3515     /* make the call by writing the pointer into pc */
3516     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3517     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3518
3519     // note: MOVFF to PCL not allowed
3520     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3521     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3522
3523
3524     /* return address is here: (X) */
3525     pic16_emitpLabelFORCE(retlbl->key);
3526
3527     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3528
3529     GpsuedoStkPtr=0;
3530     /* if we need assign a result value */
3531     if ((IS_ITEMP(IC_RESULT(ic))
3532           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3533               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3534         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3535
3536       _G.accInUse++;
3537       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3538       _G.accInUse--;
3539
3540       assignResultValue(IC_RESULT(ic), 1);
3541
3542       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3543               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3544                 
3545       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3546     }
3547
3548 //    stackParms -= use_wreg;
3549     
3550     if(stackParms>0) {
3551       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3552       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3553       if(STACK_MODEL_LARGE) {
3554         emitSKPNC;
3555         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3556       }
3557     }
3558 }
3559
3560 /*-----------------------------------------------------------------*/
3561 /* resultRemat - result  is rematerializable                       */
3562 /*-----------------------------------------------------------------*/
3563 static int resultRemat (iCode *ic)
3564 {
3565   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3566   if (SKIP_IC(ic) || ic->op == IFX)
3567     return 0;
3568
3569   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3570     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3571     if (sym->remat && !POINTER_SET(ic)) 
3572       return 1;
3573   }
3574
3575   return 0;
3576 }
3577
3578 #if defined(__BORLANDC__) || defined(_MSC_VER)
3579 #define STRCASECMP stricmp
3580 #else
3581 #define STRCASECMP strcasecmp
3582 #endif
3583
3584 #if 0
3585 /*-----------------------------------------------------------------*/
3586 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3587 /*-----------------------------------------------------------------*/
3588 static bool inExcludeList(char *s)
3589 {
3590   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3591     int i =0;
3592     
3593     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3594     if (options.excludeRegs[i] &&
3595     STRCASECMP(options.excludeRegs[i],"none") == 0)
3596         return FALSE ;
3597
3598     for ( i = 0 ; options.excludeRegs[i]; i++) {
3599         if (options.excludeRegs[i] &&
3600         STRCASECMP(s,options.excludeRegs[i]) == 0)
3601             return TRUE;
3602     }
3603     return FALSE ;
3604 }
3605 #endif
3606
3607 /*-----------------------------------------------------------------*/
3608 /* genFunction - generated code for function entry                 */
3609 /*-----------------------------------------------------------------*/
3610 static void genFunction (iCode *ic)
3611 {
3612   symbol *sym;
3613   sym_link *ftype;
3614   
3615     FENTRY;
3616     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3617
3618     pic16_labelOffset += (max_key+4);
3619     max_key=0;
3620     GpsuedoStkPtr=0;
3621     _G.nRegsSaved = 0;
3622         
3623     ftype = operandType(IC_LEFT(ic));
3624     sym = OP_SYMBOL(IC_LEFT(ic));
3625
3626     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3627       /* create an absolute section at the interrupt vector:
3628        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3629       symbol *asym;
3630       char asymname[128];
3631       pBlock *apb;
3632
3633 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3634
3635         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3636           sprintf(asymname, "ivec_%s", sym->name);
3637         else
3638           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3639   
3640         /* when an interrupt is declared as naked, do not emit the special
3641          * wrapper segment at vector address. The user should take care for
3642          * this instead. -- VR */
3643
3644         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3645           asym = newSymbol(asymname, 0);
3646           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3647           pic16_addpBlock( apb );
3648
3649           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3650           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3651           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3652           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3653           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3654                 
3655           /* mark the end of this tiny function */
3656           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3657         } else {
3658           sprintf(asymname, "%s", sym->rname);
3659         }
3660
3661         {
3662           absSym *abSym;
3663
3664             abSym = Safe_calloc(1, sizeof(absSym));
3665             strcpy(abSym->name, asymname);
3666
3667             switch( FUNC_INTNO(sym->type) ) {
3668               case 0: abSym->address = 0x000000; break;
3669               case 1: abSym->address = 0x000008; break;
3670               case 2: abSym->address = 0x000018; break;
3671               
3672               default:
3673 //                fprintf(stderr, "no interrupt number is given\n");
3674                 abSym->address = -1; break;
3675             }
3676
3677             /* relocate interrupt vectors if needed */
3678             if(abSym->address != -1)
3679               abSym->address += pic16_options.ivt_loc;
3680
3681             addSet(&absSymSet, abSym);
3682         }
3683     }
3684
3685     /* create the function header */
3686     pic16_emitcode(";","-----------------------------------------");
3687     pic16_emitcode(";"," function %s",sym->name);
3688     pic16_emitcode(";","-----------------------------------------");
3689
3690     pic16_emitcode("","%s:",sym->rname);
3691     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3692
3693     {
3694       absSym *ab;
3695
3696         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3697           if(!strcmp(ab->name, sym->rname)) {
3698             pic16_pBlockConvert2Absolute(pb);
3699             break;
3700           }
3701         }
3702     }
3703
3704     if(IFFUNC_ISNAKED(ftype)) {
3705       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3706       return;
3707     }
3708         
3709     /* if critical function then turn interrupts off */
3710     if (IFFUNC_ISCRITICAL(ftype)) {
3711       //pic16_emitcode("clr","ea");
3712     }
3713
3714     currFunc = sym;             /* update the currFunc symbol */
3715     _G.fregsUsed = sym->regsUsed;
3716     _G.sregsAlloc = newBitVect(128);
3717     
3718
3719     /* if this is an interrupt service routine then
3720      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3721     if (IFFUNC_ISISR(sym->type)) {
3722         _G.usefastretfie = 1;   /* use shadow registers by default */
3723         
3724         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3725         if(!FUNC_ISSHADOWREGS(sym->type)) {
3726           /* do not save WREG,STATUS,BSR for high priority interrupts
3727            * because they are stored in the hardware shadow registers already */
3728           _G.usefastretfie = 0;
3729           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3730           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3731           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3732         }
3733
3734         /* these should really be optimized somehow, because not all
3735          * interrupt handlers modify them */
3736         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3737         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3738         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3739         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3740         
3741 //        pic16_pBlockConvert2ISR(pb);
3742     }
3743
3744     /* emit code to setup stack frame if user enabled,
3745      * and function is not main() */
3746     
3747 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3748     if(strcmp(sym->name, "main")) {
3749       if(0 
3750         || !options.ommitFramePtr 
3751 //        || sym->regsUsed
3752         || IFFUNC_ARGS(sym->type)
3753         || FUNC_HASSTACKPARM(sym->etype)
3754         ) {
3755         /* setup the stack frame */
3756         if(STACK_MODEL_LARGE)
3757           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3758         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3759
3760         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3761         if(STACK_MODEL_LARGE)
3762           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3763       }
3764     }
3765
3766     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3767           && sym->stack) {
3768
3769       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3770
3771       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3772       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3773       emitSKPC;
3774       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3775     }
3776           
3777     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3778       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3779         _G.useWreg = 0;
3780       else
3781         _G.useWreg = 1;
3782     } else
3783       _G.useWreg = 0;
3784
3785     /* if callee-save to be used for this function
3786      * then save the registers being used in this function */
3787 //    if (IFFUNC_CALLEESAVES(sym->type))
3788     if(strcmp(sym->name, "main")) {
3789       int i;
3790
3791         /* if any registers used */
3792         if (sym->regsUsed) {
3793                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3794
3795           if(!xinst) {
3796             /* save the registers used */
3797             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3798             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3799               if (bitVectBitValue(sym->regsUsed,i)) {
3800 #if 0
3801                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3802 #endif
3803                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3804                 _G.nRegsSaved++;
3805
3806                 if(!pic16_regWithIdx(i)->wasUsed) {
3807                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3808                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3809                   pic16_regWithIdx(i)->wasUsed = 1;
3810                 }
3811               }
3812             }
3813           } else {
3814             
3815             /* xinst */
3816             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3817             for(i=0;i<sym->regsUsed->size;i++) {
3818               if(bitVectBitValue(sym->regsUsed, i)) {
3819                 _G.nRegsSaved++;
3820               }
3821             }
3822                         
3823 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3824           }
3825
3826           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3827
3828         }
3829     }
3830         
3831     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3832 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3833 }
3834
3835 /*-----------------------------------------------------------------*/
3836 /* genEndFunction - generates epilogue for functions               */
3837 /*-----------------------------------------------------------------*/
3838 static void genEndFunction (iCode *ic)
3839 {
3840   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3841
3842     FENTRY;
3843
3844     if(IFFUNC_ISNAKED(sym->type)) {
3845       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3846       return;
3847     }
3848
3849     _G.stack_lat = 0;
3850
3851     /* add code for ISCRITICAL */
3852     if(IFFUNC_ISCRITICAL(sym->type)) {
3853       /* if critical function, turn on interrupts */
3854       
3855       /* TODO: add code here -- VR */
3856     }
3857     
3858 //    sym->regsUsed = _G.fregsUsed;
3859     
3860     /* now we need to restore the registers */
3861     /* if any registers used */
3862
3863     /* first restore registers that might be used for stack access */
3864     if(_G.sregsAllocSet) {
3865     regs *sr;
3866     
3867       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3868       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3869         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3870       }
3871     }
3872
3873     if (strcmp(sym->name, "main") && sym->regsUsed) {
3874       int i;
3875
3876         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3877         /* restore registers used */
3878         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3879         for ( i = sym->regsUsed->size; i >= 0; i--) {
3880           if (bitVectBitValue(sym->regsUsed,i)) {
3881             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3882             _G.nRegsSaved--;
3883           }
3884         }
3885         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3886     }
3887
3888       
3889
3890     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3891           && sym->stack) {
3892       if (sym->stack == 1) {
3893         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3894         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3895       } else {
3896         // we have to add more than one...
3897         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3898         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3899         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3900         emitSKPNC;
3901         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3902         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3903         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3904       }
3905     }
3906
3907     if(strcmp(sym->name, "main")) {
3908       if(0
3909         || !options.ommitFramePtr
3910 //        || sym->regsUsed
3911         || IFFUNC_ARGS(sym->type)
3912         || FUNC_HASSTACKPARM(sym->etype)
3913         ) {
3914         /* restore stack frame */
3915         if(STACK_MODEL_LARGE)
3916           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3917         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3918       }
3919     }
3920
3921     _G.useWreg = 0;
3922
3923     if (IFFUNC_ISISR(sym->type)) {
3924       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3925       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3926       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3927       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3928
3929       if(!FUNC_ISSHADOWREGS(sym->type)) {
3930         /* do not restore interrupt vector for WREG,STATUS,BSR
3931          * for high priority interrupt, see genFunction */
3932         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3933         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3934         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3935       }
3936 //      _G.interruptvector = 0;         /* sanity check */
3937
3938
3939       /* if debug then send end of function */
3940 /*      if (options.debug && currFunc)  */
3941       if (currFunc) {
3942         debugFile->writeEndFunction (currFunc, ic, 1);
3943       }
3944         
3945       if(_G.usefastretfie)
3946         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3947       else
3948         pic16_emitpcodeNULLop(POC_RETFIE);
3949
3950       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3951       
3952       _G.usefastretfie = 0;
3953       return;
3954     }
3955
3956     if (IFFUNC_ISCRITICAL(sym->type)) {
3957       pic16_emitcode("setb","ea");
3958     }
3959
3960     /* if debug then send end of function */
3961     if (currFunc) {
3962       debugFile->writeEndFunction (currFunc, ic, 1);
3963     }
3964
3965     /* insert code to restore stack frame, if user enabled it
3966      * and function is not main() */
3967          
3968
3969     pic16_emitpcodeNULLop(POC_RETURN);
3970
3971     /* Mark the end of a function */
3972     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3973 }
3974
3975
3976 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3977 {
3978   unsigned long lit=1;
3979   operand *op;
3980
3981     op = IC_LEFT(ic);
3982   
3983     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3984     if(AOP_TYPE(op) == AOP_LIT) {
3985       if(!IS_FLOAT(operandType( op ))) {
3986         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3987       } else {
3988         union {
3989           unsigned long lit_int;
3990           float lit_float;
3991         } info;
3992         
3993         /* take care if literal is a float */
3994         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3995         lit = info.lit_int;
3996       }
3997     }
3998
3999     if(is_LitOp(op)) {
4000       pic16_movLit2f(dest, lit);
4001     } else {
4002       if(dest->type == PO_WREG && (offset == 0)) {
4003         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4004       return;
4005     }
4006     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4007   }
4008 }
4009
4010 /*-----------------------------------------------------------------*/
4011 /* genRet - generate code for return statement                     */
4012 /*-----------------------------------------------------------------*/
4013 static void genRet (iCode *ic)
4014 {
4015   int size;
4016   operand *left;
4017
4018     FENTRY;
4019         /* if we have no return value then
4020          * just generate the "ret" */
4021         
4022         if (!IC_LEFT(ic)) 
4023                 goto jumpret;       
4024     
4025         /* we have something to return then
4026          * move the return value into place */
4027         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4028         size = AOP_SIZE(IC_LEFT(ic));
4029
4030         if(size <= 4) {
4031           if(size>3)
4032             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4033           
4034           if(size>2)
4035             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4036
4037           if(size>1)
4038             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4039           
4040           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4041
4042         } else {
4043                 /* >32-bits, setup stack and FSR0 */
4044                 while (size--) {
4045 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4046 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4047
4048                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4049
4050 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4051                         GpsuedoStkPtr++;
4052                 }
4053                         
4054                 /* setup FSR0 */
4055                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4056                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4057
4058                 if(STACK_MODEL_LARGE) {
4059                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4060                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4061                 } else {
4062                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4063                 }
4064         }
4065                                 
4066 #if 0
4067         /* old code, left here for reference -- VR */    
4068         while (size--) {
4069           char *l ;
4070
4071                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4072                         /* #NOCHANGE */
4073                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4074                         pic16_emitpcomment("push %s",l);
4075                         pushed++;
4076                 } else {
4077                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4078                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4079                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4080                         
4081                         if (strcmp(fReturn[offset],l)) {
4082                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4083                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4084                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4085                                 } else {
4086                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4087                                 }
4088                                 
4089                                 if(size) {
4090                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4091                                 }
4092                                 offset++;
4093                         }
4094                 }
4095         }    
4096
4097         if (pushed) {
4098                 while(pushed) {
4099                         pushed--;
4100                         if (strcmp(fReturn[pushed],"a"))
4101                                 pic16_emitcode("pop",fReturn[pushed]);
4102                         else
4103                                 pic16_emitcode("pop","acc");
4104                 }
4105         }
4106 #endif
4107
4108
4109         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4110     
4111 jumpret:
4112         /* generate a jump to the return label
4113          * if the next is not the return statement */
4114         if (!(ic->next && ic->next->op == LABEL
4115                 && IC_LABEL(ic->next) == returnLabel)) {
4116         
4117                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4118                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4119         }
4120 }
4121
4122 /*-----------------------------------------------------------------*/
4123 /* genLabel - generates a label                                    */
4124 /*-----------------------------------------------------------------*/
4125 static void genLabel (iCode *ic)
4126 {
4127   FENTRY;
4128
4129   /* special case never generate */
4130   if (IC_LABEL(ic) == entryLabel)
4131     return ;
4132
4133   pic16_emitpLabel(IC_LABEL(ic)->key);
4134 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4135 }
4136
4137 /*-----------------------------------------------------------------*/
4138 /* genGoto - generates a goto                                      */
4139 /*-----------------------------------------------------------------*/
4140 //tsd
4141 static void genGoto (iCode *ic)
4142 {
4143   FENTRY;
4144   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4145 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4146 }
4147
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genMultbits :- multiplication of bits                           */
4151 /*-----------------------------------------------------------------*/
4152 static void genMultbits (operand *left, 
4153                          operand *right, 
4154                          operand *result)
4155 {
4156   FENTRY;
4157
4158   if(!pic16_sameRegs(AOP(result),AOP(right)))
4159     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4160
4161   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4162   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4163   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4164
4165 }
4166
4167
4168 /*-----------------------------------------------------------------*/
4169 /* genMultOneByte : 8 bit multiplication & division                */
4170 /*-----------------------------------------------------------------*/
4171 static void genMultOneByte (operand *left,
4172                             operand *right,
4173                             operand *result)
4174 {
4175
4176   FENTRY;
4177   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4178   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4179
4180   /* (if two literals, the value is computed before) */
4181   /* if one literal, literal on the right */
4182   if (AOP_TYPE(left) == AOP_LIT){
4183     operand *t = right;
4184     right = left;
4185     left = t;
4186   }
4187
4188         /* size is already checked in genMult == 1 */
4189 //      size = AOP_SIZE(result);
4190
4191         if (AOP_TYPE(right) == AOP_LIT){
4192                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4193                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4194                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4195                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4196         } else {
4197                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4198                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4199                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4200                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4201         }
4202         
4203         pic16_genMult8X8_8 (left, right,result);
4204 }
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genMultOneWord : 16 bit multiplication                          */
4208 /*-----------------------------------------------------------------*/
4209 static void genMultOneWord (operand *left,
4210                             operand *right,
4211                             operand *result)
4212 {
4213   FENTRY;
4214   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4216
4217   /* (if two literals, the value is computed before)
4218    * if one literal, literal on the right */
4219   if (AOP_TYPE(left) == AOP_LIT){
4220     operand *t = right;
4221     right = left;
4222     left = t;
4223   }
4224
4225   /* size is checked already == 2 */
4226 //  size = AOP_SIZE(result);
4227
4228   if (AOP_TYPE(right) == AOP_LIT) {
4229     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4230       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4231       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4232       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4233   } else {
4234     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4235       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4236       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4237       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4238   }
4239         
4240   pic16_genMult16X16_16(left, right,result);
4241 }
4242
4243 /*-----------------------------------------------------------------*/
4244 /* genMultOneLong : 32 bit multiplication                          */
4245 /*-----------------------------------------------------------------*/
4246 static void genMultOneLong (operand *left,
4247                             operand *right,
4248                             operand *result)
4249 {
4250   FENTRY;
4251   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4252   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4253
4254   /* (if two literals, the value is computed before)
4255    * if one literal, literal on the right */
4256   if (AOP_TYPE(left) == AOP_LIT){
4257     operand *t = right;
4258     right = left;
4259     left = t;
4260   }
4261
4262   /* size is checked already == 4 */
4263 //  size = AOP_SIZE(result);
4264
4265   if (AOP_TYPE(right) == AOP_LIT) {
4266     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4267         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4268         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4269         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4270   } else {
4271     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4272         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4273         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4274         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4275   }
4276         
4277   pic16_genMult32X32_32(left, right,result);
4278 }
4279
4280
4281
4282 /*-----------------------------------------------------------------*/
4283 /* genMult - generates code for multiplication                     */
4284 /*-----------------------------------------------------------------*/
4285 static void genMult (iCode *ic)
4286 {
4287   operand *left = IC_LEFT(ic);
4288   operand *right = IC_RIGHT(ic);
4289   operand *result= IC_RESULT(ic);   
4290
4291     FENTRY;
4292         /* assign the amsops */
4293         pic16_aopOp (left,ic,FALSE);
4294         pic16_aopOp (right,ic,FALSE);
4295         pic16_aopOp (result,ic,TRUE);
4296
4297         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4298
4299         /* special cases first *
4300         * both are bits */
4301         if (AOP_TYPE(left) == AOP_CRY
4302                 && AOP_TYPE(right)== AOP_CRY) {
4303                 genMultbits(left,right,result);
4304           goto release ;
4305         }
4306
4307         /* if both are of size == 1 */
4308         if(AOP_SIZE(left) == 1
4309                 && AOP_SIZE(right) == 1) {
4310                 genMultOneByte(left,right,result);
4311           goto release ;
4312         }
4313
4314         /* if both are of size == 2 */
4315         if(AOP_SIZE(left) == 2
4316                 && AOP_SIZE(right) == 2) {
4317                 genMultOneWord(left, right, result);
4318           goto release;
4319         }
4320         
4321         /* if both are of size == 4 */
4322         if(AOP_SIZE(left) == 4
4323                 && AOP_SIZE(right) == 4) {
4324                 genMultOneLong(left, right, result);
4325           goto release;
4326         }
4327         
4328         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4329
4330
4331         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4332         /* should have been converted to function call */
4333         assert(0) ;
4334
4335 release :
4336         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4337         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4338         pic16_freeAsmop(result,NULL,ic,TRUE); 
4339 }
4340
4341 /*-----------------------------------------------------------------*/
4342 /* genDivbits :- division of bits                                  */
4343 /*-----------------------------------------------------------------*/
4344 static void genDivbits (operand *left, 
4345                         operand *right, 
4346                         operand *result)
4347 {
4348   char *l;
4349
4350     FENTRY;
4351     /* the result must be bit */    
4352     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4353     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4354
4355     MOVA(l);    
4356
4357     pic16_emitcode("div","ab");
4358     pic16_emitcode("rrc","a");
4359     pic16_aopPut(AOP(result),"c",0);
4360 }
4361
4362 /*-----------------------------------------------------------------*/
4363 /* genDivOneByte : 8 bit division                                  */
4364 /*-----------------------------------------------------------------*/
4365 static void genDivOneByte (operand *left,
4366                            operand *right,
4367                            operand *result)
4368 {
4369   sym_link *opetype = operandType(result);
4370   char *l ;
4371   symbol *lbl ;
4372   int size,offset;
4373
4374         /* result = divident / divisor
4375          * - divident may be a register or a literal,
4376          * - divisor may be a register or a literal,
4377          * so there are 3 cases (literal / literal is optimized
4378          * by the front-end) to handle.
4379          * In addition we must handle signed and unsigned, which
4380          * result in 6 final different cases -- VR */
4381
4382     FENTRY;
4383     
4384     size = AOP_SIZE(result) - 1;
4385     offset = 1;
4386     /* signed or unsigned */
4387     if (SPEC_USIGN(opetype)) {
4388       pCodeOp *pct1,    /* count */
4389                 *pct2,  /* reste */
4390                 *pct3;  /* temp */
4391       symbol *label1, *label2, *label3;;
4392
4393
4394         /* unsigned is easy */
4395
4396         pct1 = pic16_popGetTempReg(1);
4397         pct2 = pic16_popGetTempReg(1);
4398         pct3 = pic16_popGetTempReg(1);
4399         
4400         label1 = newiTempLabel(NULL);
4401         label2 = newiTempLabel(NULL);
4402         label3 = newiTempLabel(NULL);
4403
4404         /* the following algorithm is extracted from divuint.c */
4405
4406         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4407         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4408         
4409         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4410
4411         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4412         
4413         pic16_emitpLabel(label1->key);
4414         
4415         emitCLRC;
4416         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4417
4418
4419         emitCLRC;
4420         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4421         
4422
4423         emitSKPNC;
4424         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4425         
4426         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4427         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4428         
4429         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4430         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4431         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4432         
4433         pic16_emitpLabel( label3->key );
4434         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4435         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4436         
4437         
4438
4439         pic16_emitpLabel(label2->key);
4440         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4441         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4442         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4443         
4444         /* result is in wreg */
4445         if(AOP_TYPE(result) != AOP_ACC)
4446                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4447
4448         pic16_popReleaseTempReg( pct3, 1);
4449         pic16_popReleaseTempReg( pct2, 1);
4450         pic16_popReleaseTempReg( pct1, 1);
4451
4452         return ;
4453     }
4454
4455     /* signed is a little bit more difficult */
4456
4457     /* save the signs of the operands */
4458     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4459     MOVA(l);    
4460     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4461     pic16_emitcode("push","acc"); /* save it on the stack */
4462
4463     /* now sign adjust for both left & right */
4464     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4465     MOVA(l);       
4466     lbl = newiTempLabel(NULL);
4467     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4468     pic16_emitcode("cpl","a");   
4469     pic16_emitcode("inc","a");
4470     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4471     pic16_emitcode("mov","b,a");
4472
4473     /* sign adjust left side */
4474     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4475     MOVA(l);
4476
4477     lbl = newiTempLabel(NULL);
4478     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4479     pic16_emitcode("cpl","a");
4480     pic16_emitcode("inc","a");
4481     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4482
4483     /* now the division */
4484     pic16_emitcode("div","ab");
4485     /* we are interested in the lower order
4486     only */
4487     pic16_emitcode("mov","b,a");
4488     lbl = newiTempLabel(NULL);
4489     pic16_emitcode("pop","acc");   
4490     /* if there was an over flow we don't 
4491     adjust the sign of the result */
4492     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4493     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4494     CLRC;
4495     pic16_emitcode("clr","a");
4496     pic16_emitcode("subb","a,b");
4497     pic16_emitcode("mov","b,a");
4498     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4499
4500     /* now we are done */
4501     pic16_aopPut(AOP(result),"b",0);
4502     if(size > 0){
4503         pic16_emitcode("mov","c,b.7");
4504         pic16_emitcode("subb","a,acc");   
4505     }
4506     while (size--)
4507         pic16_aopPut(AOP(result),"a",offset++);
4508
4509 }
4510
4511 /*-----------------------------------------------------------------*/
4512 /* genDiv - generates code for division                            */
4513 /*-----------------------------------------------------------------*/
4514 static void genDiv (iCode *ic)
4515 {
4516     operand *left = IC_LEFT(ic);
4517     operand *right = IC_RIGHT(ic);
4518     operand *result= IC_RESULT(ic);   
4519
4520
4521         /* Division is a very lengthy algorithm, so it is better
4522          * to call support routines than inlining algorithm.
4523          * Division functions written here just in case someone
4524          * wants to inline and not use the support libraries -- VR */
4525
4526     FENTRY;
4527     
4528     /* assign the amsops */
4529     pic16_aopOp (left,ic,FALSE);
4530     pic16_aopOp (right,ic,FALSE);
4531     pic16_aopOp (result,ic,TRUE);
4532
4533     /* special cases first */
4534     /* both are bits */
4535     if (AOP_TYPE(left) == AOP_CRY &&
4536         AOP_TYPE(right)== AOP_CRY) {
4537         genDivbits(left,right,result);
4538         goto release ;
4539     }
4540
4541     /* if both are of size == 1 */
4542     if (AOP_SIZE(left) == 1 &&
4543         AOP_SIZE(right) == 1 ) {
4544         genDivOneByte(left,right,result);
4545         goto release ;
4546     }
4547
4548     /* should have been converted to function call */
4549     assert(0);
4550 release :
4551     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4552     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4553     pic16_freeAsmop(result,NULL,ic,TRUE); 
4554 }
4555
4556 /*-----------------------------------------------------------------*/
4557 /* genModbits :- modulus of bits                                   */
4558 /*-----------------------------------------------------------------*/
4559 static void genModbits (operand *left, 
4560                         operand *right, 
4561                         operand *result)
4562 {
4563   char *l;
4564
4565     FENTRY;  
4566     
4567     werror(W_POSSBUG2, __FILE__, __LINE__);
4568     /* the result must be bit */    
4569     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4570     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4571
4572     MOVA(l);       
4573
4574     pic16_emitcode("div","ab");
4575     pic16_emitcode("mov","a,b");
4576     pic16_emitcode("rrc","a");
4577     pic16_aopPut(AOP(result),"c",0);
4578 }
4579
4580 /*-----------------------------------------------------------------*/
4581 /* genModOneByte : 8 bit modulus                                   */
4582 /*-----------------------------------------------------------------*/
4583 static void genModOneByte (operand *left,
4584                            operand *right,
4585                            operand *result)
4586 {
4587   sym_link *opetype = operandType(result);
4588   char *l ;
4589   symbol *lbl ;
4590
4591     FENTRY;
4592     werror(W_POSSBUG2, __FILE__, __LINE__);
4593
4594     /* signed or unsigned */
4595     if (SPEC_USIGN(opetype)) {
4596         /* unsigned is easy */
4597         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4598         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4599         MOVA(l);    
4600         pic16_emitcode("div","ab");
4601         pic16_aopPut(AOP(result),"b",0);
4602         return ;
4603     }
4604
4605     /* signed is a little bit more difficult */
4606
4607     /* save the signs of the operands */
4608     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4609     MOVA(l);
4610
4611     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4612     pic16_emitcode("push","acc"); /* save it on the stack */
4613
4614     /* now sign adjust for both left & right */
4615     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4616     MOVA(l);
4617
4618     lbl = newiTempLabel(NULL);
4619     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4620     pic16_emitcode("cpl","a");   
4621     pic16_emitcode("inc","a");
4622     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4623     pic16_emitcode("mov","b,a"); 
4624
4625     /* sign adjust left side */
4626     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4627     MOVA(l);
4628
4629     lbl = newiTempLabel(NULL);
4630     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4631     pic16_emitcode("cpl","a");   
4632     pic16_emitcode("inc","a");
4633     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4634
4635     /* now the multiplication */
4636     pic16_emitcode("div","ab");
4637     /* we are interested in the lower order
4638     only */
4639     lbl = newiTempLabel(NULL);
4640     pic16_emitcode("pop","acc");   
4641     /* if there was an over flow we don't 
4642     adjust the sign of the result */
4643     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4644     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4645     CLRC ;
4646     pic16_emitcode("clr","a");
4647     pic16_emitcode("subb","a,b");
4648     pic16_emitcode("mov","b,a");
4649     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4650
4651     /* now we are done */
4652     pic16_aopPut(AOP(result),"b",0);
4653
4654 }
4655
4656 /*-----------------------------------------------------------------*/
4657 /* genMod - generates code for division                            */
4658 /*-----------------------------------------------------------------*/
4659 static void genMod (iCode *ic)
4660 {
4661   operand *left = IC_LEFT(ic);
4662   operand *right = IC_RIGHT(ic);
4663   operand *result= IC_RESULT(ic);  
4664
4665     FENTRY;
4666     
4667     /* assign the amsops */
4668     pic16_aopOp (left,ic,FALSE);
4669     pic16_aopOp (right,ic,FALSE);
4670     pic16_aopOp (result,ic,TRUE);
4671
4672     /* special cases first */
4673     /* both are bits */
4674     if (AOP_TYPE(left) == AOP_CRY &&
4675         AOP_TYPE(right)== AOP_CRY) {
4676         genModbits(left,right,result);
4677         goto release ;
4678     }
4679
4680     /* if both are of size == 1 */
4681     if (AOP_SIZE(left) == 1 &&
4682         AOP_SIZE(right) == 1 ) {
4683         genModOneByte(left,right,result);
4684         goto release ;
4685     }
4686
4687     /* should have been converted to function call */
4688     assert(0);
4689
4690 release :
4691     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4692     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4693     pic16_freeAsmop(result,NULL,ic,TRUE); 
4694 }
4695
4696 /*-----------------------------------------------------------------*/
4697 /* genIfxJump :- will create a jump depending on the ifx           */
4698 /*-----------------------------------------------------------------*/
4699 /*
4700   note: May need to add parameter to indicate when a variable is in bit space.
4701 */
4702 static void genIfxJump (iCode *ic, char *jval)
4703 {
4704   FENTRY;
4705   
4706     /* if true label then we jump if condition
4707     supplied is true */
4708     if ( IC_TRUE(ic) ) {
4709
4710         if(strcmp(jval,"a") == 0)
4711           emitSKPZ;
4712         else if (strcmp(jval,"c") == 0)
4713           emitSKPNC;
4714         else {
4715           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4716           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4717         }
4718
4719         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4720         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4721
4722     }
4723     else {
4724         /* false label is present */
4725         if(strcmp(jval,"a") == 0)
4726           emitSKPNZ;
4727         else if (strcmp(jval,"c") == 0)
4728           emitSKPC;
4729         else {
4730           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4731           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4732         }
4733
4734         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4735         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4736
4737     }
4738
4739
4740     /* mark the icode as generated */
4741     ic->generated = 1;
4742 }
4743
4744 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4745 {
4746   FENTRY;
4747   
4748     /* if true label then we jump if condition
4749     supplied is true */
4750     if ( IC_TRUE(ic) ) {
4751       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4752       pic16_emitpcode(POC_BTFSC, jop);
4753
4754       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4755       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4756
4757     } else {
4758       /* false label is present */
4759       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4760       pic16_emitpcode(POC_BTFSS, jop);
4761           
4762       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4763       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4764     }
4765
4766
4767     /* mark the icode as generated */
4768     ic->generated = 1;
4769 }
4770
4771 #if 0
4772 // not needed ATM
4773
4774 /*-----------------------------------------------------------------*/
4775 /* genSkip                                                         */
4776 /*-----------------------------------------------------------------*/
4777 static void genSkip(iCode *ifx,int status_bit)
4778 {
4779   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4780   if(!ifx)
4781     return;
4782
4783   if ( IC_TRUE(ifx) ) {
4784     switch(status_bit) {
4785     case 'z':
4786       emitSKPNZ;
4787       break;
4788
4789     case 'c':
4790       emitSKPNC;
4791       break;
4792
4793     case 'd':
4794       emitSKPDC;
4795       break;
4796
4797     }
4798
4799     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4800     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4801
4802   } else {
4803
4804     switch(status_bit) {
4805
4806     case 'z':
4807       emitSKPZ;
4808       break;
4809
4810     case 'c':
4811       emitSKPC;
4812       break;
4813
4814     case 'd':
4815       emitSKPDC;
4816       break;
4817     }
4818     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4819     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4820
4821   }
4822
4823 }
4824 #endif
4825
4826 /*-----------------------------------------------------------------*/
4827 /* genSkipc                                                        */
4828 /*-----------------------------------------------------------------*/
4829 static void genSkipc(resolvedIfx *rifx)
4830 {
4831   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4832   
4833   if(!rifx)
4834     return;
4835
4836   if(rifx->condition)
4837     emitSKPNC;
4838   else
4839     emitSKPC;
4840
4841   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4842   rifx->generated = 1;
4843 }
4844
4845 #if !(USE_SIMPLE_GENCMP)
4846 /*-----------------------------------------------------------------*/
4847 /* genSkipz2                                                       */
4848 /*-----------------------------------------------------------------*/
4849 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4850 {
4851   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4852   
4853   if(!rifx)
4854     return;
4855
4856   if( (rifx->condition ^ invert_condition) & 1)
4857     emitSKPZ;
4858   else
4859     emitSKPNZ;
4860
4861   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4862   rifx->generated = 1;
4863 }
4864 #endif
4865
4866 #if 0
4867 /*-----------------------------------------------------------------*/
4868 /* genSkipz                                                        */
4869 /*-----------------------------------------------------------------*/
4870 static void genSkipz(iCode *ifx, int condition)
4871 {
4872   if(!ifx)
4873     return;
4874
4875   if(condition)
4876     emitSKPNZ;
4877   else
4878     emitSKPZ;
4879
4880   if ( IC_TRUE(ifx) )
4881     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4882   else
4883     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4884
4885   if ( IC_TRUE(ifx) )
4886     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4887   else
4888     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4889
4890 }
4891 #endif
4892
4893 #if !(USE_SIMPLE_GENCMP)
4894 /*-----------------------------------------------------------------*/
4895 /* genSkipCond                                                     */
4896 /*-----------------------------------------------------------------*/
4897 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4898 {
4899   if(!rifx)
4900     return;
4901
4902   if(rifx->condition)
4903     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4904   else
4905     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4906
4907
4908   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4909   rifx->generated = 1;
4910 }
4911 #endif
4912
4913 #if 0
4914 /*-----------------------------------------------------------------*/
4915 /* genChkZeroes :- greater or less than comparison                 */
4916 /*     For each byte in a literal that is zero, inclusive or the   */
4917 /*     the corresponding byte in the operand with W                */
4918 /*     returns true if any of the bytes are zero                   */
4919 /*-----------------------------------------------------------------*/
4920 static int genChkZeroes(operand *op, int lit,  int size)
4921 {
4922
4923   int i;
4924   int flag =1;
4925
4926   while(size--) {
4927     i = (lit >> (size*8)) & 0xff;
4928
4929     if(i==0) {
4930       if(flag) 
4931         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4932       else
4933         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4934       flag = 0;
4935     }
4936   }
4937
4938   return (flag==0);
4939 }
4940 #endif
4941
4942
4943 /*-----------------------------------------------------------------*/
4944 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4945 /*                  aop (if it's NOT a literal) or from lit (if    */
4946 /*                  aop is a literal)                              */
4947 /*-----------------------------------------------------------------*/
4948 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4949   if (aop->type == AOP_LIT) {
4950     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4951   } else {
4952     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4953   }
4954 }
4955
4956 /*-----------------------------------------------------------------*/
4957 /* genCmp :- greater or less than comparison                       */
4958 /*-----------------------------------------------------------------*/
4959
4960 #if USE_SIMPLE_GENCMP           /* { */
4961
4962 /* genCmp performs a left < right comparison, stores
4963  * the outcome in result (if != NULL) and generates
4964  * control flow code for the ifx (if != NULL).
4965  *
4966  * This version leaves in sequences like
4967  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4968  * which should be optmized by the peephole
4969  * optimizer - RN 2005-01-01 */
4970 static void genCmp (operand *left,operand *right,
4971                     operand *result, iCode *ifx, int sign)
4972 {
4973   resolvedIfx rIfx;
4974   int size;
4975   int offs;
4976   symbol *templbl;
4977   operand *dummy;
4978   unsigned long lit;
4979   unsigned long mask;
4980   int performedLt;
4981
4982   FENTRY;
4983   
4984   assert (left && right);
4985   assert (AOP_SIZE(left) == AOP_SIZE(right));
4986
4987   size = AOP_SIZE(right) - 1;
4988   mask = (0x100UL << (size*8)) - 1;
4989   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4990   performedLt = 1;
4991   templbl = NULL;
4992   lit = 0;
4993   
4994   resolveIfx (&rIfx, ifx);
4995
4996   /* handle for special cases */
4997   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4998       return;
4999
5000   /**********************************************************************
5001    * handle bits - bit compares are promoted to int compares seemingly! *
5002    **********************************************************************/
5003 #if 0
5004   // THIS IS COMPLETELY UNTESTED!
5005   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5006     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5007     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5008     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5009
5010     emitSETC;
5011     // 1 < {0,1} is false --> clear C by skipping the next instruction
5012     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5013     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5014     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5015     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5016     emitCLRC; // only skipped for left=0 && right=1
5017
5018     goto correct_result_in_carry;
5019   } // if
5020 #endif
5021
5022   /*************************************************
5023    * make sure that left is register (or the like) *
5024    *************************************************/
5025   if (!isAOP_REGlike(left)) {
5026     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5027     assert (isAOP_LIT(left));
5028     assert (isAOP_REGlike(right));
5029     // swap left and right
5030     // left < right <==> right > left <==> (right >= left + 1)
5031     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5032
5033     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5034       // MAXVALUE < right? always false
5035       if (performedLt) emitCLRC; else emitSETC;
5036       goto correct_result_in_carry;
5037     } // if
5038
5039     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5040     // that's why we handled it above.
5041     lit++;
5042
5043     dummy = left;
5044     left = right;
5045     right = dummy;
5046
5047     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5048   } else if (isAOP_LIT(right)) {
5049     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5050   } // if
5051
5052   assert (isAOP_REGlike(left)); // left must be register or the like
5053   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5054
5055   /*************************************************
5056    * special cases go here                         *
5057    *************************************************/
5058
5059   if (isAOP_LIT(right)) {
5060     if (!sign) {
5061       // unsigned comparison to a literal
5062       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5063       if (lit == 0) {
5064         // unsigned left < 0? always false
5065         if (performedLt) emitCLRC; else emitSETC;
5066         goto correct_result_in_carry;
5067       }
5068     } else {
5069       // signed comparison to a literal
5070       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5071       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5072         // signed left < 0x80000000? always false
5073         if (performedLt) emitCLRC; else emitSETC;
5074         goto correct_result_in_carry;
5075       } else if (lit == 0) {
5076         // compare left < 0; set CARRY if SIGNBIT(left) is set
5077         if (performedLt) emitSETC; else emitCLRC;
5078         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5079         if (performedLt) emitCLRC; else emitSETC;
5080         goto correct_result_in_carry;
5081       }
5082     } // if (!sign)
5083   } // right is literal
5084
5085   /*************************************************
5086    * perform a general case comparison             *
5087    * make sure we get CARRY==1 <==> left >= right  *
5088    *************************************************/
5089   // compare most significant bytes
5090   //DEBUGpc ("comparing bytes at offset %d", size);
5091   if (!sign) {
5092     // unsigned comparison
5093     mov2w_regOrLit (AOP(right), lit, size);
5094     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5095   } else {
5096     // signed comparison
5097     // (add 2^n to both operands then perform an unsigned comparison)
5098     if (isAOP_LIT(right)) {
5099       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5100       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5101
5102       if (litbyte == 0x80) {
5103         // left >= 0x80 -- always true, but more bytes to come
5104         pic16_mov2w (AOP(left), size);
5105         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5106         emitSETC;
5107       } else {
5108         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5109         pic16_mov2w (AOP(left), size);
5110         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5111         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5112       } // if
5113     } else {
5114       /* using PRODL as a temporary register here */
5115       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5116       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5117       pic16_mov2w (AOP(left), size);
5118       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5119       pic16_emitpcode (POC_MOVWF, pctemp);
5120       pic16_mov2w (AOP(right), size);
5121       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5122       pic16_emitpcode (POC_SUBFW, pctemp);
5123       //pic16_popReleaseTempReg(pctemp, 1);
5124     }
5125   } // if (!sign)
5126
5127   // compare remaining bytes (treat as unsigned case from above)
5128   templbl = newiTempLabel ( NULL );
5129   offs = size;
5130   while (offs--) {
5131     //DEBUGpc ("comparing bytes at offset %d", offs);
5132     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5133     mov2w_regOrLit (AOP(right), lit, offs);
5134     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5135   } // while (offs)
5136   pic16_emitpLabel (templbl->key);
5137   goto result_in_carry;
5138
5139 result_in_carry:
5140   
5141   /****************************************************
5142    * now CARRY contains the result of the comparison: *
5143    * SUBWF sets CARRY iff                             *
5144    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5145    * (F=left, W=right)                                *
5146    ****************************************************/
5147
5148   if (performedLt) {
5149     if (result && AOP_TYPE(result) != AOP_CRY) {
5150       // value will be stored
5151       emitTOGC;
5152     } else {
5153       // value wil only be used in the following genSkipc()
5154       rIfx.condition ^= 1;
5155     }
5156   } // if
5157
5158 correct_result_in_carry:
5159
5160   // assign result to variable (if neccessary)
5161   if (result && AOP_TYPE(result) != AOP_CRY) {
5162     //DEBUGpc ("assign result");
5163     size = AOP_SIZE(result);
5164     while (size--) {
5165       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5166     } // while
5167     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5168   } // if (result)
5169
5170   // perform conditional jump
5171   if (ifx) {
5172     //DEBUGpc ("generate control flow");
5173     genSkipc (&rIfx);
5174     ifx->generated = 1;
5175   } // if
5176 }
5177
5178 #elif 1         /* } */
5179                 /* { */
5180       /* original code */
5181 static void genCmp (operand *left,operand *right,
5182                     operand *result, iCode *ifx, int sign)
5183 {
5184   int size; //, offset = 0 ;
5185   unsigned long lit = 0L,i = 0;
5186   resolvedIfx rFalseIfx;
5187   //  resolvedIfx rTrueIfx;
5188   symbol *truelbl;
5189   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5190 /*
5191   if(ifx) {
5192     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5193     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5194   }
5195 */
5196
5197   FENTRY;
5198   
5199   resolveIfx(&rFalseIfx,ifx);
5200   truelbl  = newiTempLabel(NULL);
5201   size = max(AOP_SIZE(left),AOP_SIZE(right));
5202
5203   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5204
5205 #define _swapp
5206
5207   /* if literal is on the right then swap with left */
5208   if ((AOP_TYPE(right) == AOP_LIT)) {
5209     operand *tmp = right ;
5210     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5211     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5212 #ifdef _swapp
5213
5214     lit = (lit - 1) & mask;
5215     right = left;
5216     left = tmp;
5217     rFalseIfx.condition ^= 1;
5218 #endif
5219
5220   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5221     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5222   }
5223
5224
5225   //if(IC_TRUE(ifx) == NULL)
5226   /* if left & right are bit variables */
5227   if (AOP_TYPE(left) == AOP_CRY &&
5228       AOP_TYPE(right) == AOP_CRY ) {
5229     assert (0 && "bit variables used in genCmp");
5230     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5231     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5232   } else {
5233     /* subtract right from left if at the
5234        end the carry flag is set then we know that
5235        left is greater than right */
5236
5237     symbol *lbl  = newiTempLabel(NULL);
5238
5239 #if 0
5240         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5241                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5242 #endif
5243
5244 #ifndef _swapp
5245     if(AOP_TYPE(right) == AOP_LIT) {
5246
5247       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5248
5249       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5250
5251       /* special cases */
5252
5253       if(lit == 0) {
5254
5255         if(sign != 0) 
5256           genSkipCond(&rFalseIfx,left,size-1,7);
5257         else 
5258           /* no need to compare to 0...*/
5259           /* NOTE: this is a de-generate compare that most certainly 
5260            *       creates some dead code. */
5261           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5262
5263         if(ifx) ifx->generated = 1;
5264         return;
5265
5266       }
5267       size--;
5268
5269       if(size == 0) {
5270         //i = (lit >> (size*8)) & 0xff;
5271         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5272         
5273         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5274
5275         i = ((0-lit) & 0xff);
5276         if(sign) {
5277           if( i == 0x81) { 
5278             /* lit is 0x7f, all signed chars are less than
5279              * this except for 0x7f itself */
5280             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5281             genSkipz2(&rFalseIfx,0);
5282           } else {
5283             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5284             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5285             genSkipc(&rFalseIfx);
5286           }
5287
5288         } else {
5289           if(lit == 1) {
5290             genSkipz2(&rFalseIfx,1);
5291           } else {
5292             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5293             genSkipc(&rFalseIfx);
5294           }
5295         }
5296
5297         if(ifx) ifx->generated = 1;
5298         return;
5299       }
5300
5301       /* chars are out of the way. now do ints and longs */
5302
5303
5304       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5305         
5306       /* special cases */
5307
5308       if(sign) {
5309
5310         if(lit == 0) {
5311           genSkipCond(&rFalseIfx,left,size,7);
5312           if(ifx) ifx->generated = 1;
5313           return;
5314         }
5315
5316         if(lit <0x100) {
5317           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5318
5319           //rFalseIfx.condition ^= 1;
5320           //genSkipCond(&rFalseIfx,left,size,7);
5321           //rFalseIfx.condition ^= 1;
5322
5323           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5324           if(rFalseIfx.condition)
5325             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5326           else
5327             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5328
5329           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5330           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5331           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5332
5333           while(size > 1)
5334             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5335
5336           if(rFalseIfx.condition) {
5337             emitSKPZ;
5338             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5339
5340           } else {
5341             emitSKPNZ;
5342           }
5343
5344           genSkipc(&rFalseIfx);
5345           pic16_emitpLabel(truelbl->key);
5346           if(ifx) ifx->generated = 1;
5347           return;
5348
5349         }
5350
5351         if(size == 1) {
5352
5353           if( (lit & 0xff) == 0) {
5354             /* lower byte is zero */
5355             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5356             i = ((lit >> 8) & 0xff) ^0x80;
5357             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5358             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5359             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5360             genSkipc(&rFalseIfx);
5361
5362
5363             if(ifx) ifx->generated = 1;
5364             return;
5365
5366           }
5367         } else {
5368           /* Special cases for signed longs */
5369           if( (lit & 0xffffff) == 0) {
5370             /* lower byte is zero */
5371             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372             i = ((lit >> 8*3) & 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
5384         }
5385
5386
5387         if(lit & (0x80 << (size*8))) {
5388           /* lit is negative */
5389           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5390
5391           //genSkipCond(&rFalseIfx,left,size,7);
5392
5393           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5394
5395           if(rFalseIfx.condition)
5396             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5397           else
5398             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5399
5400
5401         } else {
5402           /* lit is positive */
5403           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5404           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5405           if(rFalseIfx.condition)
5406             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5407           else
5408             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5409
5410         }
5411
5412         /*
5413           This works, but is only good for ints.
5414           It also requires a "known zero" register.
5415           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5416           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5417           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5418           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5419           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5420           genSkipc(&rFalseIfx);
5421
5422           pic16_emitpLabel(truelbl->key);
5423           if(ifx) ifx->generated = 1;
5424           return;
5425         **/
5426           
5427         /* There are no more special cases, so perform a general compare */
5428   
5429         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5430         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5431
5432         while(size--) {
5433
5434           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5435           emitSKPNZ;
5436           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5437         }
5438         //rFalseIfx.condition ^= 1;
5439         genSkipc(&rFalseIfx);
5440
5441         pic16_emitpLabel(truelbl->key);
5442
5443         if(ifx) ifx->generated = 1;
5444         return;
5445
5446
5447       }
5448
5449
5450       /* sign is out of the way. So now do an unsigned compare */
5451       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5452
5453
5454       /* General case - compare to an unsigned literal on the right.*/
5455
5456       i = (lit >> (size*8)) & 0xff;
5457       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5458       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5459       while(size--) {
5460         i = (lit >> (size*8)) & 0xff;
5461
5462         if(i) {
5463           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5464           emitSKPNZ;
5465           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5466         } else {
5467           /* this byte of the lit is zero, 
5468            *if it's not the last then OR in the variable */
5469           if(size)
5470             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5471         }
5472       }
5473
5474
5475       pic16_emitpLabel(lbl->key);
5476 //      pic16_emitpLabel(truelbl->key);
5477       //if(emitFinalCheck)
5478       genSkipc(&rFalseIfx);
5479       if(sign)
5480         pic16_emitpLabel(truelbl->key);
5481
5482       if(ifx) ifx->generated = 1;
5483       return;
5484
5485
5486     }
5487 #endif  // _swapp
5488
5489     if(AOP_TYPE(left) == AOP_LIT) {
5490       //symbol *lbl = newiTempLabel(NULL);
5491
5492       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5493
5494
5495       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5496
5497       /* Special cases */
5498       if((lit == 0) && (sign == 0)){
5499
5500         size--;
5501         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5502         while(size) 
5503           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5504
5505         genSkipz2(&rFalseIfx,0);
5506         if(ifx) ifx->generated = 1;
5507         return;
5508       }
5509
5510       if(size==1) {
5511         /* Special cases */
5512         lit &= 0xff;
5513         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5514           /* degenerate compare can never be true */
5515           if(rFalseIfx.condition == 0)
5516             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5517
5518           if(ifx) ifx->generated = 1;
5519           return;
5520         }
5521
5522         if(sign) {
5523           /* signed comparisons to a literal byte */
5524
5525           int lp1 = (lit+1) & 0xff;
5526
5527           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5528           switch (lp1) {
5529           case 0:
5530             rFalseIfx.condition ^= 1;
5531             genSkipCond(&rFalseIfx,right,0,7);
5532             break;
5533           case 0x7f:
5534             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5535             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5536             genSkipz2(&rFalseIfx,1);
5537             break;
5538           default:
5539             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5540             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5541             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5542             rFalseIfx.condition ^= 1;
5543             genSkipc(&rFalseIfx);
5544             break;
5545           }
5546         } else {
5547           /* unsigned comparisons to a literal byte */
5548
5549           switch(lit & 0xff ) {
5550           case 0:
5551             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552             genSkipz2(&rFalseIfx,0);
5553             break;
5554           case 0x7f:
5555             rFalseIfx.condition ^= 1;
5556             genSkipCond(&rFalseIfx,right,0,7);
5557             break;
5558
5559           default:
5560             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5561             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5562             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5563             rFalseIfx.condition ^= 1;
5564             if (AOP_TYPE(result) == AOP_CRY)
5565               genSkipc(&rFalseIfx);
5566             else {
5567               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5568               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5569             }         
5570             break;
5571           }
5572         }
5573
5574         if(ifx) ifx->generated = 1;
5575         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5576                 goto check_carry;
5577         return;
5578
5579       } else {
5580
5581         /* Size is greater than 1 */
5582
5583         if(sign) {
5584           int lp1 = lit+1;
5585
5586           size--;
5587
5588           if(lp1 == 0) {
5589             /* this means lit = 0xffffffff, or -1 */
5590
5591
5592             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5593             rFalseIfx.condition ^= 1;
5594             genSkipCond(&rFalseIfx,right,size,7);
5595             if(ifx) ifx->generated = 1;
5596
5597             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5598               goto check_carry;
5599
5600             return;
5601           }
5602
5603           if(lit == 0) {
5604             int s = size;
5605
5606             if(rFalseIfx.condition) {
5607               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5608               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5609             }
5610
5611             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5612             while(size--)
5613               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5614
5615
5616             emitSKPZ;
5617             if(rFalseIfx.condition) {
5618               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5619               pic16_emitpLabel(truelbl->key);
5620             }else {
5621               rFalseIfx.condition ^= 1;
5622               genSkipCond(&rFalseIfx,right,s,7);
5623             }
5624
5625             if(ifx) ifx->generated = 1;
5626
5627             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5628               goto check_carry;
5629
5630             return;
5631           }
5632
5633           if((size == 1) &&  (0 == (lp1&0xff))) {
5634             /* lower byte of signed word is zero */
5635             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5636             i = ((lp1 >> 8) & 0xff) ^0x80;
5637             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5638             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5639             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5640
5641             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5642               emitTOGC;
5643               if(ifx) ifx->generated = 1;
5644               goto check_carry;
5645             } else {
5646               rFalseIfx.condition ^= 1;
5647               genSkipc(&rFalseIfx);
5648               if(ifx) ifx->generated = 1;
5649             }
5650
5651             return;
5652           }
5653
5654           if(lit & (0x80 << (size*8))) {
5655             /* Lit is less than zero */
5656             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5657             //rFalseIfx.condition ^= 1;
5658             //genSkipCond(&rFalseIfx,left,size,7);
5659             //rFalseIfx.condition ^= 1;
5660             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5661             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5662
5663             if(rFalseIfx.condition)
5664               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5665             else
5666               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5667
5668
5669           } else {
5670             /* Lit is greater than or equal to zero */
5671             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5672             //rFalseIfx.condition ^= 1;
5673             //genSkipCond(&rFalseIfx,right,size,7);
5674             //rFalseIfx.condition ^= 1;
5675
5676             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5677             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5678
5679             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5680             if(rFalseIfx.condition)
5681               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5682             else
5683               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5684
5685           }
5686
5687           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5688           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5689
5690           while(size--) {
5691
5692             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5693             emitSKPNZ;
5694             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5695           }
5696           rFalseIfx.condition ^= 1;
5697           //rFalseIfx.condition = 1;
5698           genSkipc(&rFalseIfx);
5699
5700           pic16_emitpLabel(truelbl->key);
5701
5702           if(ifx) ifx->generated = 1;
5703
5704
5705           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5706             goto check_carry;
5707
5708           return;
5709           // end of if (sign)
5710         } else {
5711
5712           /* compare word or long to an unsigned literal on the right.*/
5713
5714
5715           size--;
5716           if(lit < 0xff) {
5717             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5718             switch (lit) {
5719             case 0:
5720               break; /* handled above */
5721 /*
5722             case 0xff:
5723               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5724               while(size--)
5725                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5726               genSkipz2(&rFalseIfx,0);
5727               break;
5728 */
5729             default:
5730               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5731               while(--size)
5732                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5733
5734               emitSKPZ;
5735               if(rFalseIfx.condition)
5736                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5737               else
5738                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5739
5740
5741               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5742               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5743
5744               rFalseIfx.condition ^= 1;
5745               genSkipc(&rFalseIfx);
5746             }
5747
5748             pic16_emitpLabel(truelbl->key);
5749
5750             if(ifx) ifx->generated = 1;
5751
5752             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5753               goto check_carry;
5754
5755             return;
5756           }
5757
5758
5759           lit++;
5760           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5761           i = (lit >> (size*8)) & 0xff;
5762
5763           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5764           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5765
5766           while(size--) {
5767             i = (lit >> (size*8)) & 0xff;
5768
5769             if(i) {
5770               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5771               emitSKPNZ;
5772               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5773             } else {
5774               /* this byte of the lit is zero, 
5775                * if it's not the last then OR in the variable */
5776               if(size)
5777                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5778             }
5779           }
5780
5781
5782           pic16_emitpLabel(lbl->key);
5783
5784           rFalseIfx.condition ^= 1;
5785
5786           genSkipc(&rFalseIfx);
5787         }
5788
5789         if(sign)
5790           pic16_emitpLabel(truelbl->key);
5791         if(ifx) ifx->generated = 1;
5792
5793             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5794               goto check_carry;
5795
5796         return;
5797       }
5798     }
5799     /* Compare two variables */
5800
5801     DEBUGpic16_emitcode(";sign","%d",sign);
5802
5803     size--;
5804     if(sign) {
5805       /* Sigh. thus sucks... */
5806       if(size) {
5807         pCodeOp *pctemp;
5808         
5809         pctemp = pic16_popGetTempReg(1);
5810         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5811         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5812         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5813         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5814         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5815         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5816         pic16_popReleaseTempReg(pctemp, 1);
5817       } else {
5818         /* Signed char comparison */
5819         /* Special thanks to Nikolai Golovchenko for this snippet */
5820         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5821         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5822         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5823         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5824         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5825         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5826
5827         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5828         genSkipc(&rFalseIfx);
5829           
5830         if(ifx) ifx->generated = 1;
5831
5832             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5833               goto check_carry;
5834
5835         return;
5836       }
5837
5838     } else {
5839
5840       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5841       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5842     }
5843
5844
5845     /* The rest of the bytes of a multi-byte compare */
5846     while (size) {
5847
5848       emitSKPZ;
5849       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5850       size--;
5851
5852       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5854
5855
5856     }
5857
5858     pic16_emitpLabel(lbl->key);
5859
5860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5861     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5862         (AOP_TYPE(result) == AOP_REG)) {
5863       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5864       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5865     } else {
5866       genSkipc(&rFalseIfx);
5867     }         
5868     //genSkipc(&rFalseIfx);
5869     if(ifx) ifx->generated = 1;
5870
5871
5872             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5873               goto check_carry;
5874
5875     return;
5876
5877   }
5878
5879 check_carry:
5880   if ((AOP_TYPE(result) != AOP_CRY) 
5881         && AOP_SIZE(result)) {
5882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5883
5884     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5885
5886     pic16_outBitC(result);
5887   } else {
5888     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5889     /* if the result is used in the next
5890        ifx conditional branch then generate
5891        code a little differently */
5892     if (ifx )
5893       genIfxJump (ifx,"c");
5894     else
5895       pic16_outBitC(result);
5896     /* leave the result in acc */
5897   }
5898
5899 }
5900
5901 #elif 0 /* VR version of genCmp() */    /* } else { */
5902
5903 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5904 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5905         operand *result, int offset, int invert_op)
5906 {
5907   /* add code here */
5908   
5909   /* check condition, > or < ?? */
5910   if(rIfx->condition != 0)invert_op ^= 1;
5911   
5912   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5913
5914   if(!ifx)invert_op ^= 1;
5915
5916   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5917       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5918   
5919   /* do selection */
5920   if(!invert_op)return POC_CPFSGT;
5921   else return POC_CPFSLT;
5922 }
5923
5924 static int compareAopfirstpass=1;
5925
5926 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5927             operand *oper, int offset, operand *result,
5928             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5929             symbol *tlbl)
5930 {
5931   int op;
5932   symbol *truelbl;
5933
5934   /* invert if there is a result to be loaded, in order to fit,
5935    * SETC/CLRC sequence */
5936   if(AOP_SIZE(result))invert_op ^= 1;
5937
5938 //  if(sign && !offset)invert_op ^= 1;
5939   
5940 //  if(sign)invert_op ^= 1;
5941   
5942   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5943
5944   if(AOP_SIZE(result) && compareAopfirstpass) {
5945     if(!ifx) {
5946       if(pcop2)
5947         pic16_emitpcode(POC_SETF, pcop2);
5948       else
5949         emitSETC;
5950     } else {
5951       if(pcop2)
5952         pic16_emitpcode(POC_CLRF, pcop2);
5953       else
5954         emitCLRC;
5955     }
5956   }
5957
5958   compareAopfirstpass = 0;
5959
5960       /* there is a bug when comparing operands with size > 1,
5961        * because higher bytes can be equal and test should be performed
5962        * to the next lower byte, current algorithm, considers operands
5963        * inequal in these cases! -- VR 20041107 */
5964
5965     
5966   if(pcop)
5967     pic16_emitpcode(op, pcop);
5968   else
5969     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5970
5971
5972   if((!sign || !offset) && AOP_SIZE(result)) {
5973     if(!ifx) {
5974       if(pcop2)
5975         pic16_emitpcode(POC_CLRF, pcop2);
5976         else
5977         emitCLRC;
5978     } else {
5979       if(pcop2)
5980         pic16_emitpcode(POC_SETF, pcop2);
5981       else
5982         emitSETC;
5983     }
5984     
5985     /* don't emit final branch (offset == 0) */
5986     if(offset) {
5987
5988       if(pcop2)
5989         pic16_emitpcode(POC_RRCF, pcop2);
5990
5991       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5992     }
5993   } else {
5994     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5995       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5996             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5997
5998       truelbl = newiTempLabel( NULL );
5999       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6000       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6001         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6002       else
6003         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6004       pic16_emitpLabel(truelbl->key);
6005     } else {
6006       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6007     }
6008   }
6009 }
6010
6011 static void genCmp (operand *left, operand *right,
6012                     operand *result, iCode *ifx, int sign)
6013 {
6014   int size, cmpop=1;
6015   long lit = 0L;
6016   resolvedIfx rFalseIfx;
6017   symbol *falselbl, *tlbl;
6018
6019     FENTRY;
6020     
6021     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6022
6023     resolveIfx(&rFalseIfx, ifx);
6024     size = max(AOP_SIZE(left), AOP_SIZE(right));
6025     
6026     /* if left & right are bit variables */
6027     if(AOP_TYPE(left) == AOP_CRY
6028       && AOP_TYPE(right) == AOP_CRY ) {
6029
6030         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6031         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6032         
6033         werror(W_POSSBUG2, __FILE__, __LINE__);
6034         exit(-1);
6035     }
6036     
6037     /* if literal is on the right then swap with left */
6038     if((AOP_TYPE(right) == AOP_LIT)) {
6039       operand *tmp = right ;
6040 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6041
6042         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6043
6044 //      lit = (lit - 1) & mask;
6045         right = left;
6046         left = tmp;
6047         rFalseIfx.condition ^= 1;               /* reverse compare */
6048     } else
6049     if ((AOP_TYPE(left) == AOP_LIT)) {
6050       /* float compares are handled by support functions */
6051       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6052     }
6053
6054     /* actual comparing algorithm */
6055 //    size = AOP_SIZE( right );
6056
6057     falselbl = newiTempLabel( NULL );
6058     if(AOP_TYPE(left) == AOP_LIT) {
6059       /* compare to literal */
6060       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6061       
6062       if(sign) {
6063         pCodeOp *pct, *pct2;
6064         symbol *tlbl1;
6065
6066         /* signed compare */
6067         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6068
6069         /* using PRODL:PRODH as a temporary register here */
6070         pct = pic16_popCopyReg(&pic16_pc_prodl);
6071         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6072         tlbl = newiTempLabel( NULL );
6073         
6074         /* first compare signs:
6075          *  a. if both are positive, compare just like unsigned
6076          *  b. if both are negative, invert cmpop, compare just like unsigned
6077          *  c. if different signs, determine the result directly */
6078
6079         size--;
6080
6081 #if 1
6082         /* { */
6083         tlbl1 = newiTempLabel( NULL );
6084 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6085
6086         if(lit > 0) {
6087
6088           /* literal is zero or positive:
6089            *  a. if carry is zero, too, continue compare,
6090            *  b. if carry is set, then continue depending on cmpop ^ condition:
6091            *    1. '<' return false (literal < variable),
6092            *    2. '>' return true (literal > variable) */
6093 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6094           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6095           
6096           
6097           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6098           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6099         } else 
6100         if(lit < 0) {
6101           
6102           /* literal is negative:
6103            *  a. if carry is set, too, continue compare,
6104            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6105            *    1. '<' return true (literal < variable),
6106            *    2. '>' return false (literal > variable) */
6107 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6108           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6109           
6110           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6111           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6112         }
6113 #if 1
6114         else {
6115           /* lit == 0 */
6116           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6117           
6118           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6119           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6120         }
6121 #endif
6122         
6123         
6124         pic16_emitpLabel( tlbl1->key );
6125 #endif  /* } */
6126
6127         compareAopfirstpass=1;
6128 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6129 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6130 //        pic16_emitpcode(POC_MOVWF, pct);
6131
6132 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6133         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6134 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6135         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6136
6137         /* generic case */        
6138           while( size-- ) {
6139 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6140 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6141 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6142 //            pic16_emitpcode(POC_MOVWF, pct);
6143
6144 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6145             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6146             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6147 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6148 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6149           }
6150         
6151         if(ifx)ifx->generated = 1;
6152
6153         if(AOP_SIZE(result)) {
6154           pic16_emitpLabel(tlbl->key);
6155           pic16_emitpLabel(falselbl->key);
6156           pic16_outBitOp( result, pct2 );
6157         } else {
6158           pic16_emitpLabel(tlbl->key);
6159         }
6160       } else {
6161
6162         /* unsigned compare */      
6163         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6164     
6165         compareAopfirstpass=1;
6166         while(size--) {
6167           
6168           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6169           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6170
6171         }
6172         if(ifx)ifx->generated = 1;
6173
6174         if(AOP_SIZE(result)) {
6175           pic16_emitpLabel(falselbl->key);
6176           pic16_outBitC( result );
6177         }
6178
6179       }
6180     } else {
6181       /* compare registers */
6182       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6183
6184
6185       if(sign) {
6186         pCodeOp *pct, *pct2;
6187         
6188         /* signed compare */
6189         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6190
6191         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6192         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6193         tlbl = newiTempLabel( NULL );
6194         
6195         compareAopfirstpass=1;
6196
6197         size--;
6198         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6199 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6200         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6201         pic16_emitpcode(POC_MOVWF, pct);
6202
6203         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6204 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6205         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6206
6207         /* WREG already holds left + 0x80 */
6208         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6209         
6210         while( size-- ) {
6211           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6212 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6213           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6214           pic16_emitpcode(POC_MOVWF, pct);
6215                 
6216           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6217 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6218           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6219
6220           /* WREG already holds left + 0x80 */
6221           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6222 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6223         }
6224         
6225         if(ifx)ifx->generated = 1;
6226
6227         if(AOP_SIZE(result)) {
6228           pic16_emitpLabel(tlbl->key);
6229           pic16_emitpLabel(falselbl->key);
6230           pic16_outBitOp( result, pct2 );
6231         } else {
6232           pic16_emitpLabel(tlbl->key);
6233         }
6234
6235       } else {
6236         /* unsigned compare */      
6237         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6238
6239         compareAopfirstpass=1;
6240         while(size--) {
6241           
6242           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6243           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6244
6245         }
6246
6247         if(ifx)ifx->generated = 1;
6248         if(AOP_SIZE(result)) {
6249
6250           pic16_emitpLabel(falselbl->key);
6251           pic16_outBitC( result );
6252         }
6253
6254       }
6255     }
6256 }
6257
6258 #endif  /* } */
6259
6260
6261
6262 /*-----------------------------------------------------------------*/
6263 /* genCmpGt :- greater than comparison                             */
6264 /*-----------------------------------------------------------------*/
6265 static void genCmpGt (iCode *ic, iCode *ifx)
6266 {
6267   operand *left, *right, *result;
6268   sym_link *letype , *retype;
6269   int sign ;
6270
6271     FENTRY;
6272     
6273     left = IC_LEFT(ic);
6274     right= IC_RIGHT(ic);
6275     result = IC_RESULT(ic);
6276
6277     letype = getSpec(operandType(left));
6278     retype =getSpec(operandType(right));
6279     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6280     /* assign the amsops */
6281     pic16_aopOp (left,ic,FALSE);
6282     pic16_aopOp (right,ic,FALSE);
6283     pic16_aopOp (result,ic,TRUE);
6284
6285     genCmp(right, left, result, ifx, sign);
6286
6287     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6288     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6289     pic16_freeAsmop(result,NULL,ic,TRUE); 
6290 }
6291
6292 /*-----------------------------------------------------------------*/
6293 /* genCmpLt - less than comparisons                                */
6294 /*-----------------------------------------------------------------*/
6295 static void genCmpLt (iCode *ic, iCode *ifx)
6296 {
6297   operand *left, *right, *result;
6298   sym_link *letype , *retype;
6299   int sign ;
6300
6301     FENTRY;
6302
6303     left = IC_LEFT(ic);
6304     right= IC_RIGHT(ic);
6305     result = IC_RESULT(ic);
6306
6307     letype = getSpec(operandType(left));
6308     retype =getSpec(operandType(right));
6309     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6310
6311     /* assign the amsops */
6312     pic16_aopOp (left,ic,FALSE);
6313     pic16_aopOp (right,ic,FALSE);
6314     pic16_aopOp (result,ic,TRUE);
6315
6316     genCmp(left, right, result, ifx, sign);
6317
6318     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6319     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6320     pic16_freeAsmop(result,NULL,ic,TRUE); 
6321 }
6322
6323 #if 0
6324 // not needed ATM
6325 // FIXME reenable literal optimisation when the pic16 port is stable
6326
6327 /*-----------------------------------------------------------------*/
6328 /* genc16bit2lit - compare a 16 bit value to a literal             */
6329 /*-----------------------------------------------------------------*/
6330 static void genc16bit2lit(operand *op, int lit, int offset)
6331 {
6332   int i;
6333
6334   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6335   if( (lit&0xff) == 0) 
6336     i=1;
6337   else
6338     i=0;
6339
6340   switch( BYTEofLONG(lit,i)) { 
6341   case 0:
6342     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6343     break;
6344   case 1:
6345     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6346     break;
6347   case 0xff:
6348     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6349     break;
6350   default:
6351     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6352     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6353   }
6354
6355   i ^= 1;
6356
6357   switch( BYTEofLONG(lit,i)) { 
6358   case 0:
6359     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6360     break;
6361   case 1:
6362     emitSKPNZ;
6363     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6364     break;
6365   case 0xff:
6366     emitSKPNZ;
6367     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6368     break;
6369   default:
6370     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6371     emitSKPNZ;
6372     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6373
6374   }
6375
6376 }
6377 #endif
6378
6379 #if 0
6380 // not needed ATM
6381 /*-----------------------------------------------------------------*/
6382 /* gencjneshort - compare and jump if not equal                    */
6383 /*-----------------------------------------------------------------*/
6384 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6385 {
6386   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6387   int offset = 0;
6388   int res_offset = 0;  /* the result may be a different size then left or right */
6389   int res_size = AOP_SIZE(result);
6390   resolvedIfx rIfx;
6391   symbol *lbl, *lbl_done;
6392
6393   unsigned long lit = 0L;
6394   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6395
6396   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6397   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6398   if(result)
6399     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6400   resolveIfx(&rIfx,ifx);
6401   lbl =  newiTempLabel(NULL);
6402   lbl_done =  newiTempLabel(NULL);
6403
6404
6405   /* if the left side is a literal or 
6406      if the right is in a pointer register and left 
6407      is not */
6408   if ((AOP_TYPE(left) == AOP_LIT) || 
6409       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6410     operand *t = right;
6411     right = left;
6412     left = t;
6413   }
6414   if(AOP_TYPE(right) == AOP_LIT)
6415     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6416
6417   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6418     preserve_result = 1;
6419
6420   if(result && !preserve_result)
6421     {
6422       int i;
6423       for(i = 0; i < AOP_SIZE(result); i++)
6424         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6425     }
6426
6427
6428   /* if the right side is a literal then anything goes */
6429   if (AOP_TYPE(right) == AOP_LIT &&
6430       AOP_TYPE(left) != AOP_DIR ) {
6431     switch(size) {
6432     case 2:
6433       genc16bit2lit(left, lit, 0);
6434       emitSKPZ;
6435       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6436       break;
6437     default:
6438       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6439       while (size--) {
6440         if(lit & 0xff) {
6441           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6442           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6443         } else {
6444           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6445         }
6446
6447         emitSKPZ;
6448         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6449         offset++;
6450         if(res_offset < res_size-1)
6451           res_offset++;
6452         lit >>= 8;
6453       }
6454       break;
6455     }
6456   }
6457
6458   /* if the right side is in a register or in direct space or
6459      if the left is a pointer register & right is not */    
6460   else if (AOP_TYPE(right) == AOP_REG ||
6461            AOP_TYPE(right) == AOP_DIR || 
6462            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6463            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6464     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6465     int lbl_key = lbl->key;
6466
6467     if(result) {
6468       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6469       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6470     }else {
6471       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6472       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6473               __FUNCTION__,__LINE__);
6474       return;
6475     }
6476    
6477 /*     switch(size) { */
6478 /*     case 2: */
6479 /*       genc16bit2lit(left, lit, 0); */
6480 /*       emitSKPNZ; */
6481 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6482 /*       break; */
6483 /*     default: */
6484     while (size--) {
6485       int emit_skip=1;
6486       if((AOP_TYPE(left) == AOP_DIR) && 
6487          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6488
6489         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6490         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6491
6492       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6493             
6494         switch (lit & 0xff) {
6495         case 0:
6496           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497           break;
6498         case 1:
6499           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6500           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6501           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6502           emit_skip=0;
6503           break;
6504         case 0xff:
6505           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6506           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6507           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6508           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6509           emit_skip=0;
6510           break;
6511         default:
6512           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6514         }
6515         lit >>= 8;
6516
6517       } else {
6518         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6519       }
6520       if(emit_skip) {
6521         if(AOP_TYPE(result) == AOP_CRY) {
6522           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6523           if(rIfx.condition)
6524             emitSKPNZ;
6525           else
6526             emitSKPZ;
6527           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6528         } else {
6529           /* fix me. probably need to check result size too */
6530           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6531           if(rIfx.condition)
6532             emitSKPZ;
6533           else
6534             emitSKPNZ;
6535           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6536           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6537         }
6538         if(ifx)
6539           ifx->generated=1;
6540       }
6541       emit_skip++;
6542       offset++;
6543       if(res_offset < res_size-1)
6544         res_offset++;
6545     }
6546 /*       break; */
6547 /*     } */
6548   } else if(AOP_TYPE(right) == AOP_REG &&
6549             AOP_TYPE(left) != AOP_DIR){
6550
6551     while(size--) {
6552       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6553       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6554       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6555       if(rIfx.condition)
6556         emitSKPNZ;
6557       else
6558         emitSKPZ;
6559       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6560       offset++;
6561       if(res_offset < res_size-1)
6562         res_offset++;
6563     }
6564       
6565   }else{
6566     /* right is a pointer reg need both a & b */
6567     while(size--) {
6568       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6569       if(strcmp(l,"b"))
6570         pic16_emitcode("mov","b,%s",l);
6571       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6572       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6573       offset++;
6574     }
6575   }
6576
6577   if(result && preserve_result)
6578     {
6579       int i;
6580       for(i = 0; i < AOP_SIZE(result); i++)
6581         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6582     }
6583
6584   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6585
6586   if(result && preserve_result)
6587     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6588
6589   if(!rIfx.condition)
6590     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6591
6592   pic16_emitpLabel(lbl->key);
6593
6594   if(result && preserve_result)
6595     {
6596       int i;
6597       for(i = 0; i < AOP_SIZE(result); i++)
6598         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6599
6600       pic16_emitpLabel(lbl_done->key);
6601    }
6602
6603   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6604
6605   if(ifx)
6606     ifx->generated = 1;
6607 }
6608 #endif
6609
6610 #if 0
6611 /*-----------------------------------------------------------------*/
6612 /* gencjne - compare and jump if not equal                         */
6613 /*-----------------------------------------------------------------*/
6614 static void gencjne(operand *left, operand *right, iCode *ifx)
6615 {
6616     symbol *tlbl  = newiTempLabel(NULL);
6617
6618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6619     gencjneshort(left, right, lbl);
6620
6621     pic16_emitcode("mov","a,%s",one);
6622     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6623     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6624     pic16_emitcode("clr","a");
6625     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6626
6627     pic16_emitpLabel(lbl->key);
6628     pic16_emitpLabel(tlbl->key);
6629
6630 }
6631 #endif
6632
6633
6634 /*-----------------------------------------------------------------*/
6635 /* is_LitOp - check if operand has to be treated as literal        */
6636 /*-----------------------------------------------------------------*/
6637 static bool is_LitOp(operand *op)
6638 {
6639   return ((AOP_TYPE(op) == AOP_LIT)
6640       || ( (AOP_TYPE(op) == AOP_PCODE)
6641           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6642               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6643 }
6644
6645 /*-----------------------------------------------------------------*/
6646 /* is_LitAOp - check if operand has to be treated as literal        */
6647 /*-----------------------------------------------------------------*/
6648 static bool is_LitAOp(asmop *aop)
6649 {
6650   return ((aop->type == AOP_LIT)
6651       || ( (aop->type == AOP_PCODE)
6652           && ( (aop->aopu.pcop->type == PO_LITERAL)
6653               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6654 }
6655
6656
6657
6658 /*-----------------------------------------------------------------*/
6659 /* genCmpEq - generates code for equal to                          */
6660 /*-----------------------------------------------------------------*/
6661 static void genCmpEq (iCode *ic, iCode *ifx)
6662 {
6663   operand *left, *right, *result;
6664   symbol *falselbl = newiTempLabel(NULL);
6665   symbol *donelbl = newiTempLabel(NULL);
6666
6667   int preserve_result = 0;
6668   int generate_result = 0;
6669   int i=0;
6670   unsigned long lit = -1;
6671
6672   FENTRY;
6673   
6674   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6675   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6676   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6677  
6678   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6679
6680   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6681     {
6682       werror(W_POSSBUG2, __FILE__, __LINE__);
6683       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6684       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6685       goto release;
6686     }
6687
6688   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6689     {
6690       operand *tmp = right ;
6691       right = left;
6692       left = tmp;
6693     }
6694
6695   if (AOP_TYPE(right) == AOP_LIT) {
6696     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6697   }
6698
6699   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6700     preserve_result = 1;
6701
6702   if(result && AOP_SIZE(result))
6703     generate_result = 1;
6704
6705   if(generate_result && !preserve_result)
6706     {
6707       for(i = 0; i < AOP_SIZE(result); i++)
6708         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6709     }
6710
6711   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6712   for(i=0; i < AOP_SIZE(left); i++)
6713     {
6714       if(AOP_TYPE(left) != AOP_ACC)
6715         {
6716           if(is_LitOp(left))
6717             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6718           else
6719             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6720         }
6721       if(is_LitOp(right)) {
6722         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6723           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6724         }
6725       } else
6726         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6727
6728       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6729     }
6730
6731   // result == true
6732
6733   if(generate_result && preserve_result)
6734     {
6735       for(i = 0; i < AOP_SIZE(result); i++)
6736         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6737     }
6738
6739   if(generate_result)
6740     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6741
6742   if(generate_result && preserve_result)
6743     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6744
6745   if(ifx && IC_TRUE(ifx))
6746     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6747
6748   if(ifx && IC_FALSE(ifx))
6749     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6750
6751   pic16_emitpLabel(falselbl->key);
6752
6753   // result == false
6754
6755   if(ifx && IC_FALSE(ifx))
6756     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6757
6758   if(generate_result && preserve_result)
6759     {
6760       for(i = 0; i < AOP_SIZE(result); i++)
6761         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6762     }
6763
6764   pic16_emitpLabel(donelbl->key);
6765
6766   if(ifx)
6767     ifx->generated = 1;
6768
6769 release:
6770   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6771   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6772   pic16_freeAsmop(result,NULL,ic,TRUE);
6773
6774 }
6775
6776
6777 #if 0
6778 // old version kept for reference
6779
6780 /*-----------------------------------------------------------------*/
6781 /* genCmpEq - generates code for equal to                          */
6782 /*-----------------------------------------------------------------*/
6783 static void genCmpEq (iCode *ic, iCode *ifx)
6784 {
6785     operand *left, *right, *result;
6786     unsigned long lit = 0L;
6787     int size,offset=0;
6788     symbol *falselbl  = newiTempLabel(NULL);
6789
6790
6791     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6792
6793     if(ifx)
6794       DEBUGpic16_emitcode ("; ifx is non-null","");
6795     else
6796       DEBUGpic16_emitcode ("; ifx is null","");
6797
6798     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6799     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6800     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6801
6802     size = max(AOP_SIZE(left),AOP_SIZE(right));
6803
6804     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6805
6806     /* if literal, literal on the right or 
6807     if the right is in a pointer register and left 
6808     is not */
6809     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6810         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6811       operand *tmp = right ;
6812       right = left;
6813       left = tmp;
6814     }
6815
6816
6817     if(ifx && !AOP_SIZE(result)){
6818         symbol *tlbl;
6819         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6820         /* if they are both bit variables */
6821         if (AOP_TYPE(left) == AOP_CRY &&
6822             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6823                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6824             if(AOP_TYPE(right) == AOP_LIT){
6825                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6826                 if(lit == 0L){
6827                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6828                     pic16_emitcode("cpl","c");
6829                 } else if(lit == 1L) {
6830                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6831                 } else {
6832                     pic16_emitcode("clr","c");
6833                 }
6834                 /* AOP_TYPE(right) == AOP_CRY */
6835             } else {
6836                 symbol *lbl = newiTempLabel(NULL);
6837                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6839                 pic16_emitcode("cpl","c");
6840                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6841             }
6842             /* if true label then we jump if condition
6843             supplied is true */
6844             tlbl = newiTempLabel(NULL);
6845             if ( IC_TRUE(ifx) ) {
6846                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6847                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6848             } else {
6849                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6850                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6851             }
6852             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6853
6854                 {
6855                 /* left and right are both bit variables, result is carry */
6856                         resolvedIfx rIfx;
6857               
6858                         resolveIfx(&rIfx,ifx);
6859
6860                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6861                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6862                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6863                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6864                         genSkipz2(&rIfx,0);
6865                 }
6866         } else {
6867
6868                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6869
6870                         /* They're not both bit variables. Is the right a literal? */
6871                         if(AOP_TYPE(right) == AOP_LIT) {
6872                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6873             
6874                         switch(size) {
6875
6876                                 case 1:
6877                                         switch(lit & 0xff) {
6878                                                 case 1:
6879                                                                 if ( IC_TRUE(ifx) ) {
6880                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6881                                                                         emitSKPNZ;
6882                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6883                                                                 } else {
6884                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6885                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6886                                                                 }
6887                                                                 break;
6888                                                 case 0xff:
6889                                                                 if ( IC_TRUE(ifx) ) {
6890                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6891                                                                         emitSKPNZ;
6892                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6893                                                                 } else {
6894                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6895                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6896                                                                 }
6897                                                                 break;
6898                                                 default:
6899                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6900                                                                 if(lit)
6901                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6902                                                                 genSkip(ifx,'z');
6903                                         } // switch lit
6904
6905
6906                                         /* end of size == 1 */
6907                                         break;
6908               
6909                                 case 2:
6910                                         genc16bit2lit(left,lit,offset);
6911                                         genSkip(ifx,'z');
6912                                         break;
6913                                         /* end of size == 2 */
6914
6915                                 default:
6916                                         /* size is 4 */
6917                                         if(lit==0) {
6918                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6919                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6920                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6921                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6922                                                 genSkip(ifx,'z');
6923                                         } else {
6924                                                 /* search for patterns that can be optimized */
6925
6926                                                 genc16bit2lit(left,lit,0);
6927                                                 lit >>= 16;
6928                                                 if(lit) {
6929                                                                 if(IC_TRUE(ifx))
6930                                                                 emitSKPZ; // if hi word unequal
6931                                                                 else
6932                                                                 emitSKPNZ; // if hi word equal
6933                                                                 // fail early
6934                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6935                                                         genc16bit2lit(left,lit,2);
6936                                                         genSkip(ifx,'z');
6937                                                 } else {
6938                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6939                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6940                                                         genSkip(ifx,'z');
6941                                                 }
6942                                         }
6943                                                 pic16_emitpLabel(falselbl->key);
6944                                                 break;
6945
6946                         } // switch size
6947           
6948                         ifx->generated = 1;
6949                         goto release ;
6950             
6951
6952           } else if(AOP_TYPE(right) == AOP_CRY ) {
6953             /* we know the left is not a bit, but that the right is */
6954             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6955             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6956                       pic16_popGet(AOP(right),offset));
6957             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6958
6959             /* if the two are equal, then W will be 0 and the Z bit is set
6960              * we could test Z now, or go ahead and check the high order bytes if
6961              * the variable we're comparing is larger than a byte. */
6962
6963             while(--size)
6964               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6965
6966             if ( IC_TRUE(ifx) ) {
6967               emitSKPNZ;
6968               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6969               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6970             } else {
6971               emitSKPZ;
6972               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6973               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6974             }
6975
6976           } else {
6977             /* They're both variables that are larger than bits */
6978             int s = size;
6979
6980             tlbl = newiTempLabel(NULL);
6981
6982             while(size--) {
6983               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6984               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6985
6986               if ( IC_TRUE(ifx) ) {
6987                 if(size) {
6988                   emitSKPZ;
6989                 
6990                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6991
6992                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6993                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6994                 } else {
6995                   emitSKPNZ;
6996
6997                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6998
6999
7000                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7001                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7002                 }
7003               } else {
7004                 emitSKPZ;
7005
7006                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7007
7008                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7009                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7010               }
7011               offset++;
7012             }
7013             if(s>1 && IC_TRUE(ifx)) {
7014               pic16_emitpLabel(tlbl->key);
7015               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7016             }
7017           }
7018         }
7019         /* mark the icode as generated */
7020         ifx->generated = 1;
7021         goto release ;
7022     }
7023
7024     /* if they are both bit variables */
7025     if (AOP_TYPE(left) == AOP_CRY &&
7026         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7027         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7028         if(AOP_TYPE(right) == AOP_LIT){
7029             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7030             if(lit == 0L){
7031                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7032                 pic16_emitcode("cpl","c");
7033             } else if(lit == 1L) {
7034                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7035             } else {
7036                 pic16_emitcode("clr","c");
7037             }
7038             /* AOP_TYPE(right) == AOP_CRY */
7039         } else {
7040             symbol *lbl = newiTempLabel(NULL);
7041             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7043             pic16_emitcode("cpl","c");
7044             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7045         }
7046         /* c = 1 if egal */
7047         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7048             pic16_outBitC(result);
7049             goto release ;
7050         }
7051         if (ifx) {
7052             genIfxJump (ifx,"c");
7053             goto release ;
7054         }
7055         /* if the result is used in an arithmetic operation
7056         then put the result in place */
7057         pic16_outBitC(result);
7058     } else {
7059       
7060       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7061       gencjne(left,right,result,ifx);
7062 /*
7063       if(ifx) 
7064         gencjne(left,right,newiTempLabel(NULL));
7065       else {
7066         if(IC_TRUE(ifx)->key)
7067           gencjne(left,right,IC_TRUE(ifx)->key);
7068         else
7069           gencjne(left,right,IC_FALSE(ifx)->key);
7070         ifx->generated = 1;
7071         goto release ;
7072       }
7073       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7074         pic16_aopPut(AOP(result),"a",0);
7075         goto release ;
7076       }
7077
7078       if (ifx) {
7079         genIfxJump (ifx,"a");
7080         goto release ;
7081       }
7082 */
7083       /* if the result is used in an arithmetic operation
7084          then put the result in place */
7085 /*
7086       if (AOP_TYPE(result) != AOP_CRY) 
7087         pic16_outAcc(result);
7088 */
7089       /* leave the result in acc */
7090     }
7091
7092 release:
7093     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7094     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7095     pic16_freeAsmop(result,NULL,ic,TRUE);
7096 }
7097 #endif
7098
7099 /*-----------------------------------------------------------------*/
7100 /* ifxForOp - returns the icode containing the ifx for operand     */
7101 /*-----------------------------------------------------------------*/
7102 static iCode *ifxForOp ( operand *op, iCode *ic )
7103 {
7104   FENTRY2;
7105
7106     /* if true symbol then needs to be assigned */
7107     if (IS_TRUE_SYMOP(op))
7108         return NULL ;
7109
7110     /* if this has register type condition and
7111     the next instruction is ifx with the same operand
7112     and live to of the operand is upto the ifx only then */
7113     if (ic->next
7114         && ic->next->op == IFX
7115         && IC_COND(ic->next)->key == op->key
7116         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7117         ) {
7118                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7119           return ic->next;
7120     }
7121
7122     /*
7123     if (ic->next &&
7124         ic->next->op == IFX &&
7125         IC_COND(ic->next)->key == op->key) {
7126       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7127       return ic->next;
7128     }
7129     */
7130
7131     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7132     if (ic->next &&
7133         ic->next->op == IFX)
7134       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7135
7136     if (ic->next &&
7137         ic->next->op == IFX &&
7138         IC_COND(ic->next)->key == op->key) {
7139       DEBUGpic16_emitcode ("; "," key is okay");
7140       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7141                            OP_SYMBOL(op)->liveTo,
7142                            ic->next->seq);
7143     }
7144
7145 #if 0
7146     /* the code below is completely untested
7147      * it just allows ulong2fs.c compile -- VR */
7148          
7149     ic = ic->next;
7150     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7151                                         __FILE__, __FUNCTION__, __LINE__);
7152         
7153     /* if this has register type condition and
7154     the next instruction is ifx with the same operand
7155     and live to of the operand is upto the ifx only then */
7156     if (ic->next &&
7157         ic->next->op == IFX &&
7158         IC_COND(ic->next)->key == op->key &&
7159         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7160         return ic->next;
7161
7162     if (ic->next &&
7163         ic->next->op == IFX &&
7164         IC_COND(ic->next)->key == op->key) {
7165       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7166       return ic->next;
7167     }
7168
7169     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7170                                         __FILE__, __FUNCTION__, __LINE__);
7171
7172 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7173 #endif
7174
7175     return NULL;
7176 }
7177 /*-----------------------------------------------------------------*/
7178 /* genAndOp - for && operation                                     */
7179 /*-----------------------------------------------------------------*/
7180 static void genAndOp (iCode *ic)
7181 {
7182   operand *left,*right, *result;
7183 /*     symbol *tlbl; */
7184
7185     FENTRY;
7186
7187     /* note here that && operations that are in an
7188     if statement are taken away by backPatchLabels
7189     only those used in arthmetic operations remain */
7190     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7191     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7192     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7193
7194     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7195
7196     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7197     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7198     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7199
7200     /* if both are bit variables */
7201 /*     if (AOP_TYPE(left) == AOP_CRY && */
7202 /*         AOP_TYPE(right) == AOP_CRY ) { */
7203 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7204 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7205 /*         pic16_outBitC(result); */
7206 /*     } else { */
7207 /*         tlbl = newiTempLabel(NULL); */
7208 /*         pic16_toBoolean(left);     */
7209 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7210 /*         pic16_toBoolean(right); */
7211 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7212 /*         pic16_outBitAcc(result); */
7213 /*     } */
7214
7215     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7216     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7217     pic16_freeAsmop(result,NULL,ic,TRUE);
7218 }
7219
7220
7221 /*-----------------------------------------------------------------*/
7222 /* genOrOp - for || operation                                      */
7223 /*-----------------------------------------------------------------*/
7224 /*
7225   tsd pic port -
7226   modified this code, but it doesn't appear to ever get called
7227 */
7228
7229 static void genOrOp (iCode *ic)
7230 {
7231   operand *left,*right, *result;
7232   symbol *tlbl;
7233
7234     FENTRY;  
7235
7236   /* note here that || operations that are in an
7237     if statement are taken away by backPatchLabels
7238     only those used in arthmetic operations remain */
7239     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7240     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7241     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7242
7243     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7244
7245     /* if both are bit variables */
7246     if (AOP_TYPE(left) == AOP_CRY &&
7247         AOP_TYPE(right) == AOP_CRY ) {
7248       pic16_emitcode("clrc","");
7249       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7250                AOP(left)->aopu.aop_dir,
7251                AOP(left)->aopu.aop_dir);
7252       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7253                AOP(right)->aopu.aop_dir,
7254                AOP(right)->aopu.aop_dir);
7255       pic16_emitcode("setc","");
7256
7257     } else {
7258         tlbl = newiTempLabel(NULL);
7259         pic16_toBoolean(left);
7260         emitSKPZ;
7261         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7262         pic16_toBoolean(right);
7263         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7264
7265         pic16_outBitAcc(result);
7266     }
7267
7268     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7269     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7270     pic16_freeAsmop(result,NULL,ic,TRUE);            
7271 }
7272
7273 /*-----------------------------------------------------------------*/
7274 /* isLiteralBit - test if lit == 2^n                               */
7275 /*-----------------------------------------------------------------*/
7276 static int isLiteralBit(unsigned long lit)
7277 {
7278     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7279     0x100L,0x200L,0x400L,0x800L,
7280     0x1000L,0x2000L,0x4000L,0x8000L,
7281     0x10000L,0x20000L,0x40000L,0x80000L,
7282     0x100000L,0x200000L,0x400000L,0x800000L,
7283     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7284     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7285     int idx;
7286     
7287     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7288     for(idx = 0; idx < 32; idx++)
7289         if(lit == pw[idx])
7290             return idx+1;
7291     return 0;
7292 }
7293
7294 /*-----------------------------------------------------------------*/
7295 /* continueIfTrue -                                                */
7296 /*-----------------------------------------------------------------*/
7297 static void continueIfTrue (iCode *ic)
7298 {
7299   FENTRY;
7300   if(IC_TRUE(ic))
7301     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7302   ic->generated = 1;
7303 }
7304
7305 /*-----------------------------------------------------------------*/
7306 /* jmpIfTrue -                                                     */
7307 /*-----------------------------------------------------------------*/
7308 static void jumpIfTrue (iCode *ic)
7309 {
7310   FENTRY;
7311   if(!IC_TRUE(ic))
7312     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7313   ic->generated = 1;
7314 }
7315
7316 /*-----------------------------------------------------------------*/
7317 /* jmpTrueOrFalse -                                                */
7318 /*-----------------------------------------------------------------*/
7319 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7320 {
7321   // ugly but optimized by peephole
7322   FENTRY;
7323   if(IC_TRUE(ic)){
7324     symbol *nlbl = newiTempLabel(NULL);
7325       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7326       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7327       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7328       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7329   } else {
7330     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7331     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7332   }
7333   ic->generated = 1;
7334 }
7335
7336 /*-----------------------------------------------------------------*/
7337 /* genAnd  - code for and                                          */
7338 /*-----------------------------------------------------------------*/
7339 static void genAnd (iCode *ic, iCode *ifx)
7340 {
7341   operand *left, *right, *result;
7342   int size, offset=0;  
7343   unsigned long lit = 0L;
7344   int bytelit = 0;
7345   resolvedIfx rIfx;
7346
7347     FENTRY;
7348     
7349   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7350   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7351   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7352
7353   resolveIfx(&rIfx,ifx);
7354
7355   /* if left is a literal & right is not then exchange them */
7356   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7357       AOP_NEEDSACC(left)) {
7358     operand *tmp = right ;
7359     right = left;
7360     left = tmp;
7361   }
7362
7363   /* if result = right then exchange them */
7364   if(pic16_sameRegs(AOP(result),AOP(right))){
7365     operand *tmp = right ;
7366     right = left;
7367     left = tmp;
7368   }
7369
7370   /* if right is bit then exchange them */
7371   if (AOP_TYPE(right) == AOP_CRY &&
7372       AOP_TYPE(left) != AOP_CRY){
7373     operand *tmp = right ;
7374     right = left;
7375     left = tmp;
7376   }
7377   if(AOP_TYPE(right) == AOP_LIT)
7378     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7379
7380   size = AOP_SIZE(result);
7381
7382   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7383
7384   // if(bit & yy)
7385   // result = bit & yy;
7386   if (AOP_TYPE(left) == AOP_CRY){
7387     // c = bit & literal;
7388     if(AOP_TYPE(right) == AOP_LIT){
7389       if(lit & 1) {
7390         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7391           // no change
7392           goto release;
7393         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7394       } else {
7395         // bit(result) = 0;
7396         if(size && (AOP_TYPE(result) == AOP_CRY)){
7397           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7398           goto release;
7399         }
7400         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7401           jumpIfTrue(ifx);
7402           goto release;
7403         }
7404         pic16_emitcode("clr","c");
7405       }
7406     } else {
7407       if (AOP_TYPE(right) == AOP_CRY){
7408         // c = bit & bit;
7409         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7410         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7411       } else {
7412         // c = bit & val;
7413         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7414         // c = lsb
7415         pic16_emitcode("rrc","a");
7416         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7417       }
7418     }
7419     // bit = c
7420     // val = c
7421     if(size)
7422       pic16_outBitC(result);
7423     // if(bit & ...)
7424     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7425       genIfxJump(ifx, "c");           
7426     goto release ;
7427   }
7428
7429   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7430   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7431   if((AOP_TYPE(right) == AOP_LIT) &&
7432      (AOP_TYPE(result) == AOP_CRY) &&
7433      (AOP_TYPE(left) != AOP_CRY)){
7434     int posbit = isLiteralBit(lit);
7435     /* left &  2^n */
7436     if(posbit){
7437       posbit--;
7438       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7439       // bit = left & 2^n
7440       if(size)
7441         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7442       // if(left &  2^n)
7443       else{
7444         if(ifx){
7445 /*
7446           if(IC_TRUE(ifx)) {
7447             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7448             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7449           } else {
7450             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7451             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7452           }
7453 */
7454         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7455         size = AOP_SIZE(left);
7456
7457         {
7458           int bp = posbit, ofs=0;
7459           
7460             while(bp > 7) {
7461               bp -= 8;
7462               ofs++;
7463             }
7464
7465           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7466                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7467
7468         }
7469 /*
7470           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7471                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7472 */
7473           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7474           
7475           ifx->generated = 1;
7476         }
7477         goto release;
7478       }
7479     } else {
7480       symbol *tlbl = newiTempLabel(NULL);
7481       int sizel = AOP_SIZE(left);
7482
7483       if(size)
7484         emitSETC;
7485
7486       while(sizel--) {
7487         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7488
7489           /* patch provided by Aaron Colwell */
7490           if((posbit = isLiteralBit(bytelit)) != 0) {
7491               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7492                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7493                                                 (posbit-1),0, PO_GPR_REGISTER));
7494
7495               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7496 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7497           } else {
7498               if (bytelit == 0xff) {
7499                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7500                    * a peephole could optimize it out -- VR */
7501                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7502               } else {
7503                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7504                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7505               }
7506
7507               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7508                             pic16_popGetLabel(tlbl->key));
7509           }
7510         
7511 #if 0
7512           /* old code, left here for reference -- VR 09/2004 */
7513           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7514           // byte ==  2^n ?
7515           if((posbit = isLiteralBit(bytelit)) != 0)
7516             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7517           else{
7518             if(bytelit != 0x0FFL)
7519               pic16_emitcode("anl","a,%s",
7520                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7521             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7522           }
7523 #endif
7524         }
7525         offset++;
7526       }
7527       // bit = left & literal
7528       if(size) {
7529         emitCLRC;
7530         pic16_emitpLabel(tlbl->key);
7531       }
7532       // if(left & literal)
7533       else {
7534         if(ifx) {
7535           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7536           ifx->generated = 1;
7537         }
7538         pic16_emitpLabel(tlbl->key);
7539         goto release;
7540       }
7541     }
7542
7543     pic16_outBitC(result);
7544     goto release ;
7545   }
7546
7547   /* if left is same as result */
7548   if(pic16_sameRegs(AOP(result),AOP(left))){
7549     int know_W = -1;
7550     for(;size--; offset++,lit>>=8) {
7551       if(AOP_TYPE(right) == AOP_LIT){
7552         switch(lit & 0xff) {
7553         case 0x00:
7554           /*  and'ing with 0 has clears the result */
7555 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7556           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7557           break;
7558         case 0xff:
7559           /* and'ing with 0xff is a nop when the result and left are the same */
7560           break;
7561
7562         default:
7563           {
7564             int p = pic16_my_powof2( (~lit) & 0xff );
7565             if(p>=0) {
7566               /* only one bit is set in the literal, so use a bcf instruction */
7567 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7568               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7569
7570             } else {
7571               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7572               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7573               if(know_W != (lit&0xff))
7574                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7575               know_W = lit &0xff;
7576               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7577             }
7578           }    
7579         }
7580       } else {
7581         if (AOP_TYPE(left) == AOP_ACC) {
7582           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7583         } else {                    
7584           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7585           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7586
7587         }
7588       }
7589     }
7590
7591   } else {
7592     // left & result in different registers
7593     if(AOP_TYPE(result) == AOP_CRY){
7594       // result = bit
7595       // if(size), result in bit
7596       // if(!size && ifx), conditional oper: if(left & right)
7597       symbol *tlbl = newiTempLabel(NULL);
7598       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7599       if(size)
7600         pic16_emitcode("setb","c");
7601       while(sizer--){
7602         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7603         pic16_emitcode("anl","a,%s",
7604                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7605         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7606         offset++;
7607       }
7608       if(size){
7609         CLRC;
7610         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7611         pic16_outBitC(result);
7612       } else if(ifx)
7613         jmpTrueOrFalse(ifx, tlbl);
7614     } else {
7615       for(;(size--);offset++) {
7616         // normal case
7617         // result = left & right
7618         if(AOP_TYPE(right) == AOP_LIT){
7619           int t = (lit >> (offset*8)) & 0x0FFL;
7620           switch(t) { 
7621           case 0x00:
7622             pic16_emitcode("clrf","%s",
7623                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7624             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7625             break;
7626           case 0xff:
7627             pic16_emitcode("movf","%s,w",
7628                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7629             pic16_emitcode("movwf","%s",
7630                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7631             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7632             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7633             break;
7634           default:
7635             pic16_emitcode("movlw","0x%x",t);
7636             pic16_emitcode("andwf","%s,w",
7637                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7638             pic16_emitcode("movwf","%s",
7639                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640               
7641             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7642             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7643             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7644           }
7645           continue;
7646         }
7647
7648         if (AOP_TYPE(left) == AOP_ACC) {
7649           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7650           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7651         } else {
7652           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7653           pic16_emitcode("andwf","%s,w",
7654                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7655           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7656           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7657         }
7658         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7659         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7660       }
7661     }
7662   }
7663
7664   release :
7665     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7666   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7667   pic16_freeAsmop(result,NULL,ic,TRUE);     
7668 }
7669
7670 /*-----------------------------------------------------------------*/
7671 /* genOr  - code for or                                            */
7672 /*-----------------------------------------------------------------*/
7673 static void genOr (iCode *ic, iCode *ifx)
7674 {
7675     operand *left, *right, *result;
7676     int size, offset=0;
7677     unsigned long lit = 0L;
7678
7679     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7680
7681     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7682     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7683     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7684
7685     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7686
7687     /* if left is a literal & right is not then exchange them */
7688     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7689         AOP_NEEDSACC(left)) {
7690         operand *tmp = right ;
7691         right = left;
7692         left = tmp;
7693     }
7694
7695     /* if result = right then exchange them */
7696     if(pic16_sameRegs(AOP(result),AOP(right))){
7697         operand *tmp = right ;
7698         right = left;
7699         left = tmp;
7700     }
7701
7702     /* if right is bit then exchange them */
7703     if (AOP_TYPE(right) == AOP_CRY &&
7704         AOP_TYPE(left) != AOP_CRY){
7705         operand *tmp = right ;
7706         right = left;
7707         left = tmp;
7708     }
7709
7710     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7711
7712     if(AOP_TYPE(right) == AOP_LIT)
7713         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7714
7715     size = AOP_SIZE(result);
7716
7717     // if(bit | yy)
7718     // xx = bit | yy;
7719     if (AOP_TYPE(left) == AOP_CRY){
7720         if(AOP_TYPE(right) == AOP_LIT){
7721             // c = bit & literal;
7722             if(lit){
7723                 // lit != 0 => result = 1
7724                 if(AOP_TYPE(result) == AOP_CRY){
7725                   if(size)
7726                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7727                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7728                   //     AOP(result)->aopu.aop_dir,
7729                   //     AOP(result)->aopu.aop_dir);
7730                     else if(ifx)
7731                         continueIfTrue(ifx);
7732                     goto release;
7733                 }
7734             } else {
7735                 // lit == 0 => result = left
7736                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7737                     goto release;
7738                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7739             }
7740         } else {
7741             if (AOP_TYPE(right) == AOP_CRY){
7742               if(pic16_sameRegs(AOP(result),AOP(left))){
7743                 // c = bit | bit;
7744                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7745                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7746                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7747
7748                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7749                          AOP(result)->aopu.aop_dir,
7750                          AOP(result)->aopu.aop_dir);
7751                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7752                          AOP(right)->aopu.aop_dir,
7753                          AOP(right)->aopu.aop_dir);
7754                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7755                          AOP(result)->aopu.aop_dir,
7756                          AOP(result)->aopu.aop_dir);
7757               } else {
7758                 if( AOP_TYPE(result) == AOP_ACC) {
7759                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7760                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7761                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7762                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7763
7764                 } else {
7765
7766                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7767                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7768                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7769                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7770
7771                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7772                                  AOP(result)->aopu.aop_dir,
7773                                  AOP(result)->aopu.aop_dir);
7774                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7775                                  AOP(right)->aopu.aop_dir,
7776                                  AOP(right)->aopu.aop_dir);
7777                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7778                                  AOP(left)->aopu.aop_dir,
7779                                  AOP(left)->aopu.aop_dir);
7780                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7781                                  AOP(result)->aopu.aop_dir,
7782                                  AOP(result)->aopu.aop_dir);
7783                 }
7784               }
7785             } else {
7786                 // c = bit | val;
7787                 symbol *tlbl = newiTempLabel(NULL);
7788                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7789
7790
7791                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7792                 if( AOP_TYPE(right) == AOP_ACC) {
7793                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7794                   emitSKPNZ;
7795                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7796                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7797                 }
7798
7799
7800
7801                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7802                     pic16_emitcode(";XXX setb","c");
7803                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7804                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7805                 pic16_toBoolean(right);
7806                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7807                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7808                     jmpTrueOrFalse(ifx, tlbl);
7809                     goto release;
7810                 } else {
7811                     CLRC;
7812                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7813                 }
7814             }
7815         }
7816         // bit = c
7817         // val = c
7818         if(size)
7819             pic16_outBitC(result);
7820         // if(bit | ...)
7821         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7822             genIfxJump(ifx, "c");           
7823         goto release ;
7824     }
7825
7826     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7827     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7828     if((AOP_TYPE(right) == AOP_LIT) &&
7829        (AOP_TYPE(result) == AOP_CRY) &&
7830        (AOP_TYPE(left) != AOP_CRY)){
7831         if(lit){
7832           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7833             // result = 1
7834             if(size)
7835                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7836             else 
7837                 continueIfTrue(ifx);
7838             goto release;
7839         } else {
7840           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7841             // lit = 0, result = boolean(left)
7842             if(size)
7843                 pic16_emitcode(";XXX setb","c");
7844             pic16_toBoolean(right);
7845             if(size){
7846                 symbol *tlbl = newiTempLabel(NULL);
7847                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7848                 CLRC;
7849                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7850             } else {
7851                 genIfxJump (ifx,"a");
7852                 goto release;
7853             }
7854         }
7855         pic16_outBitC(result);
7856         goto release ;
7857     }
7858
7859     /* if left is same as result */
7860     if(pic16_sameRegs(AOP(result),AOP(left))){
7861       int know_W = -1;
7862       for(;size--; offset++,lit>>=8) {
7863         if(AOP_TYPE(right) == AOP_LIT){
7864           if((lit & 0xff) == 0)
7865             /*  or'ing with 0 has no effect */
7866             continue;
7867           else {
7868             int p = pic16_my_powof2(lit & 0xff);
7869             if(p>=0) {
7870               /* only one bit is set in the literal, so use a bsf instruction */
7871               pic16_emitpcode(POC_BSF,
7872                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7873             } else {
7874               if(know_W != (lit & 0xff))
7875                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7876               know_W = lit & 0xff;
7877               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7878             }
7879                     
7880           }
7881         } else {
7882           if (AOP_TYPE(left) == AOP_ACC) {
7883             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7884 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7885           } else {                  
7886             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7887             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7888
7889 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7890 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7891
7892           }
7893         }
7894       }
7895     } else {
7896         // left & result in different registers
7897         if(AOP_TYPE(result) == AOP_CRY){
7898             // result = bit
7899             // if(size), result in bit
7900             // if(!size && ifx), conditional oper: if(left | right)
7901             symbol *tlbl = newiTempLabel(NULL);
7902             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7903             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7904
7905
7906             if(size)
7907                 pic16_emitcode(";XXX setb","c");
7908             while(sizer--){
7909                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910                 pic16_emitcode(";XXX orl","a,%s",
7911                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7912                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7913                 offset++;
7914             }
7915             if(size){
7916                 CLRC;
7917                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7918                 pic16_outBitC(result);
7919             } else if(ifx)
7920                 jmpTrueOrFalse(ifx, tlbl);
7921         } else for(;(size--);offset++){
7922           // normal case
7923           // result = left & right
7924           if(AOP_TYPE(right) == AOP_LIT){
7925             int t = (lit >> (offset*8)) & 0x0FFL;
7926             switch(t) { 
7927             case 0x00:
7928               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7929               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7930
7931 //            pic16_emitcode("movf","%s,w",
7932 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7933 //            pic16_emitcode("movwf","%s",
7934 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7935               break;
7936             default:
7937               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7938               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7939               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7940
7941 //            pic16_emitcode("movlw","0x%x",t);
7942 //            pic16_emitcode("iorwf","%s,w",
7943 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7944 //            pic16_emitcode("movwf","%s",
7945 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7946               
7947             }
7948             continue;
7949           }
7950
7951           // faster than result <- left, anl result,right
7952           // and better if result is SFR
7953           if (AOP_TYPE(left) == AOP_ACC) {
7954             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7955 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7956           } else {
7957             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7958             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7959
7960 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7961 //          pic16_emitcode("iorwf","%s,w",
7962 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7963           }
7964           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7965 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7966         }
7967     }
7968
7969 release :
7970     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7971     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7972     pic16_freeAsmop(result,NULL,ic,TRUE);     
7973 }
7974
7975 /*-----------------------------------------------------------------*/
7976 /* genXor - code for xclusive or                                   */
7977 /*-----------------------------------------------------------------*/
7978 static void genXor (iCode *ic, iCode *ifx)
7979 {
7980   operand *left, *right, *result;
7981   int size, offset=0;
7982   unsigned long lit = 0L;
7983
7984   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7985
7986   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7987   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7988   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7989
7990   /* if left is a literal & right is not ||
7991      if left needs acc & right does not */
7992   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7993       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7994     operand *tmp = right ;
7995     right = left;
7996     left = tmp;
7997   }
7998
7999   /* if result = right then exchange them */
8000   if(pic16_sameRegs(AOP(result),AOP(right))){
8001     operand *tmp = right ;
8002     right = left;
8003     left = tmp;
8004   }
8005
8006   /* if right is bit then exchange them */
8007   if (AOP_TYPE(right) == AOP_CRY &&
8008       AOP_TYPE(left) != AOP_CRY){
8009     operand *tmp = right ;
8010     right = left;
8011     left = tmp;
8012   }
8013   if(AOP_TYPE(right) == AOP_LIT)
8014     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8015
8016   size = AOP_SIZE(result);
8017
8018   // if(bit ^ yy)
8019   // xx = bit ^ yy;
8020   if (AOP_TYPE(left) == AOP_CRY){
8021     if(AOP_TYPE(right) == AOP_LIT){
8022       // c = bit & literal;
8023       if(lit>>1){
8024         // lit>>1  != 0 => result = 1
8025         if(AOP_TYPE(result) == AOP_CRY){
8026           if(size)
8027             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8028             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8029           else if(ifx)
8030             continueIfTrue(ifx);
8031           goto release;
8032         }
8033         pic16_emitcode("setb","c");
8034       } else{
8035         // lit == (0 or 1)
8036         if(lit == 0){
8037           // lit == 0, result = left
8038           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8039             goto release;
8040           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8041         } else{
8042           // lit == 1, result = not(left)
8043           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8044             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8045             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8046             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8047             goto release;
8048           } else {
8049             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8050             pic16_emitcode("cpl","c");
8051           }
8052         }
8053       }
8054
8055     } else {
8056       // right != literal
8057       symbol *tlbl = newiTempLabel(NULL);
8058       if (AOP_TYPE(right) == AOP_CRY){
8059         // c = bit ^ bit;
8060         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8061       }
8062       else{
8063         int sizer = AOP_SIZE(right);
8064         // c = bit ^ val
8065         // if val>>1 != 0, result = 1
8066         pic16_emitcode("setb","c");
8067         while(sizer){
8068           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8069           if(sizer == 1)
8070             // test the msb of the lsb
8071             pic16_emitcode("anl","a,#0xfe");
8072           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8073           sizer--;
8074         }
8075         // val = (0,1)
8076         pic16_emitcode("rrc","a");
8077       }
8078       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8079       pic16_emitcode("cpl","c");
8080       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8081     }
8082     // bit = c
8083     // val = c
8084     if(size)
8085       pic16_outBitC(result);
8086     // if(bit | ...)
8087     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8088       genIfxJump(ifx, "c");           
8089     goto release ;
8090   }
8091
8092   if(pic16_sameRegs(AOP(result),AOP(left))){
8093     /* if left is same as result */
8094     for(;size--; offset++) {
8095       if(AOP_TYPE(right) == AOP_LIT){
8096         int t  = (lit >> (offset*8)) & 0x0FFL;
8097         if(t == 0x00L)
8098           continue;
8099         else
8100           if (IS_AOP_PREG(left)) {
8101             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8102             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8103             pic16_aopPut(AOP(result),"a",offset);
8104           } else {
8105             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8106             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8107             pic16_emitcode("xrl","%s,%s",
8108                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8109                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8110           }
8111       } else {
8112         if (AOP_TYPE(left) == AOP_ACC)
8113           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114         else {
8115           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8116           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8117 /*
8118           if (IS_AOP_PREG(left)) {
8119             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8120             pic16_aopPut(AOP(result),"a",offset);
8121           } else
8122             pic16_emitcode("xrl","%s,a",
8123                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8124 */
8125         }
8126       }
8127     }
8128   } else {
8129     // left & result in different registers
8130     if(AOP_TYPE(result) == AOP_CRY){
8131       // result = bit
8132       // if(size), result in bit
8133       // if(!size && ifx), conditional oper: if(left ^ right)
8134       symbol *tlbl = newiTempLabel(NULL);
8135       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8136       if(size)
8137         pic16_emitcode("setb","c");
8138       while(sizer--){
8139         if((AOP_TYPE(right) == AOP_LIT) &&
8140            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8141           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8142         } else {
8143           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8144           pic16_emitcode("xrl","a,%s",
8145                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8146         }
8147         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8148         offset++;
8149       }
8150       if(size){
8151         CLRC;
8152         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8153         pic16_outBitC(result);
8154       } else if(ifx)
8155         jmpTrueOrFalse(ifx, tlbl);
8156     } else for(;(size--);offset++){
8157       // normal case
8158       // result = left & right
8159       if(AOP_TYPE(right) == AOP_LIT){
8160         int t = (lit >> (offset*8)) & 0x0FFL;
8161         switch(t) { 
8162         case 0x00:
8163           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8164           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8165           pic16_emitcode("movf","%s,w",
8166                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8167           pic16_emitcode("movwf","%s",
8168                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8169           break;
8170         case 0xff:
8171           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8172           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8173           pic16_emitcode("comf","%s,w",
8174                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8175           pic16_emitcode("movwf","%s",
8176                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8177           break;
8178         default:
8179           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8180           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8181           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8182           pic16_emitcode("movlw","0x%x",t);
8183           pic16_emitcode("xorwf","%s,w",
8184                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185           pic16_emitcode("movwf","%s",
8186                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187
8188         }
8189         continue;
8190       }
8191
8192       // faster than result <- left, anl result,right
8193       // and better if result is SFR
8194       if (AOP_TYPE(left) == AOP_ACC) {
8195         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8196         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8197       } else {
8198         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8199         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8200         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8201         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8202       }
8203       if ( AOP_TYPE(result) != AOP_ACC){
8204         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8205         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8206       }
8207     }
8208   }
8209
8210   release :
8211     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8212   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8213   pic16_freeAsmop(result,NULL,ic,TRUE);     
8214 }
8215
8216 /*-----------------------------------------------------------------*/
8217 /* genInline - write the inline code out                           */
8218 /*-----------------------------------------------------------------*/
8219 static void genInline (iCode *ic)
8220 {
8221   char *buffer, *bp, *bp1;
8222     
8223         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8224
8225         _G.inLine += (!options.asmpeep);
8226
8227         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8228         strcpy(buffer,IC_INLINE(ic));
8229         
8230         while((bp1=strstr(bp, "\\n"))) {
8231           *bp1++ = '\n';
8232           *bp1++ = ' ';
8233           bp = bp1;
8234         }
8235         bp = bp1 = buffer;
8236
8237 #if 0
8238   /* This is an experimental code for #pragma inline
8239      and is temporarily disabled for 2.5.0 release */
8240         if(asmInlineMap)
8241         {
8242           symbol *sym;
8243           char *s;
8244           char *cbuf;
8245           int cblen;
8246
8247             cbuf = Safe_strdup(buffer);
8248             cblen = strlen(buffer)+1;
8249             memset(cbuf, 0, cblen);
8250
8251             bp = buffer;
8252             bp1 = cbuf;
8253             while(*bp) {
8254               if(*bp != '%')*bp1++ = *bp++;
8255               else {
8256                 int i;
8257
8258                   bp++;
8259                   i = *bp - '0';
8260                   if(i>elementsInSet(asmInlineMap))break;
8261                   
8262                   bp++;
8263                   s = indexSet(asmInlineMap, i);
8264                   DEBUGpc("searching symbol s = `%s'", s);
8265                   sym = findSym(SymbolTab, NULL, s);
8266
8267                   if(sym->reqv) {
8268                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8269                   } else {
8270                     strcat(bp1, sym->rname);
8271                   }
8272                   
8273                   while(*bp1)bp1++;
8274               }
8275               
8276               if(strlen(bp1) > cblen - 16) {
8277                 int i = strlen(cbuf);
8278                 cblen += 50;
8279                 cbuf = realloc(cbuf, cblen);
8280                 memset(cbuf+i, 0, 50);
8281                 bp1 = cbuf + i;
8282               }
8283             }
8284             
8285             free(buffer);
8286             buffer = Safe_strdup( cbuf );
8287             free(cbuf);
8288             
8289             bp = bp1 = buffer;
8290         }
8291 #endif  /* 0 */
8292
8293         /* emit each line as a code */
8294         while (*bp) {
8295                 if (*bp == '\n') {
8296                         *bp++ = '\0';
8297
8298                         if(*bp1)
8299                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8300                         bp1 = bp;
8301                 } else {
8302                         if (*bp == ':') {
8303                                 bp++;
8304                                 *bp = '\0';
8305                                 bp++;
8306
8307                                 /* print label, use this special format with NULL directive
8308                                  * to denote that the argument should not be indented with tab */
8309                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8310                                 bp1 = bp;
8311                         } if (*bp == ';') {
8312                                 /* advance to end of line (prevent splitting of comments at ':' */
8313                                 while (*bp && *bp != '\n') {
8314                                         bp++;
8315                                 } // while
8316                         } else
8317                                 bp++;
8318                 }
8319         }
8320
8321         if ((bp1 != bp) && *bp1)
8322                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8323
8324
8325     Safe_free(buffer);
8326
8327     _G.inLine -= (!options.asmpeep);
8328 }
8329
8330 /*-----------------------------------------------------------------*/
8331 /* genRRC - rotate right with carry                                */
8332 /*-----------------------------------------------------------------*/
8333 static void genRRC (iCode *ic)
8334 {
8335   operand *left , *result ;
8336   int size, offset = 0, same;
8337
8338   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8339
8340   /* rotate right with carry */
8341   left = IC_LEFT(ic);
8342   result=IC_RESULT(ic);
8343   pic16_aopOp (left,ic,FALSE);
8344   pic16_aopOp (result,ic,TRUE);
8345
8346   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8347
8348   same = pic16_sameRegs(AOP(result),AOP(left));
8349
8350   size = AOP_SIZE(result);    
8351
8352   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8353
8354   /* get the lsb and put it into the carry */
8355   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8356
8357   offset = 0 ;
8358
8359   while(size--) {
8360
8361     if(same) {
8362       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8363     } else {
8364       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8365       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8366     }
8367
8368     offset++;
8369   }
8370
8371   pic16_freeAsmop(left,NULL,ic,TRUE);
8372   pic16_freeAsmop(result,NULL,ic,TRUE);
8373 }
8374
8375 /*-----------------------------------------------------------------*/
8376 /* genRLC - generate code for rotate left with carry               */
8377 /*-----------------------------------------------------------------*/
8378 static void genRLC (iCode *ic)
8379 {    
8380   operand *left , *result ;
8381   int size, offset = 0;
8382   int same;
8383
8384   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8385   /* rotate right with carry */
8386   left = IC_LEFT(ic);
8387   result=IC_RESULT(ic);
8388   pic16_aopOp (left,ic,FALSE);
8389   pic16_aopOp (result,ic,TRUE);
8390
8391   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8392
8393   same = pic16_sameRegs(AOP(result),AOP(left));
8394
8395   /* move it to the result */
8396   size = AOP_SIZE(result);    
8397
8398   /* get the msb and put it into the carry */
8399   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8400
8401   offset = 0 ;
8402
8403   while(size--) {
8404
8405     if(same) {
8406       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8407     } else {
8408       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8409       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8410     }
8411
8412     offset++;
8413   }
8414
8415
8416   pic16_freeAsmop(left,NULL,ic,TRUE);
8417   pic16_freeAsmop(result,NULL,ic,TRUE);
8418 }
8419
8420
8421 /* gpasm can get the highest order bit with HIGH/UPPER
8422  * so the following probably is not needed -- VR */
8423  
8424 /*-----------------------------------------------------------------*/
8425 /* genGetHbit - generates code get highest order bit               */
8426 /*-----------------------------------------------------------------*/
8427 static void genGetHbit (iCode *ic)
8428 {
8429     operand *left, *result;
8430     left = IC_LEFT(ic);
8431     result=IC_RESULT(ic);
8432     pic16_aopOp (left,ic,FALSE);
8433     pic16_aopOp (result,ic,FALSE);
8434
8435     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8436     /* get the highest order byte into a */
8437     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8438     if(AOP_TYPE(result) == AOP_CRY){
8439         pic16_emitcode("rlc","a");
8440         pic16_outBitC(result);
8441     }
8442     else{
8443         pic16_emitcode("rl","a");
8444         pic16_emitcode("anl","a,#0x01");
8445         pic16_outAcc(result);
8446     }
8447
8448
8449     pic16_freeAsmop(left,NULL,ic,TRUE);
8450     pic16_freeAsmop(result,NULL,ic,TRUE);
8451 }
8452
8453 #if 0
8454 /*-----------------------------------------------------------------*/
8455 /* AccRol - rotate left accumulator by known count                 */
8456 /*-----------------------------------------------------------------*/
8457 static void AccRol (int shCount)
8458 {
8459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8460     shCount &= 0x0007;              // shCount : 0..7
8461     switch(shCount){
8462         case 0 :
8463             break;
8464         case 1 :
8465             pic16_emitcode("rl","a");
8466             break;
8467         case 2 :
8468             pic16_emitcode("rl","a");
8469             pic16_emitcode("rl","a");
8470             break;
8471         case 3 :
8472             pic16_emitcode("swap","a");
8473             pic16_emitcode("rr","a");
8474             break;
8475         case 4 :
8476             pic16_emitcode("swap","a");
8477             break;
8478         case 5 :
8479             pic16_emitcode("swap","a");
8480             pic16_emitcode("rl","a");
8481             break;
8482         case 6 :
8483             pic16_emitcode("rr","a");
8484             pic16_emitcode("rr","a");
8485             break;
8486         case 7 :
8487             pic16_emitcode("rr","a");
8488             break;
8489     }
8490 }
8491 #endif
8492
8493 /*-----------------------------------------------------------------*/
8494 /* AccLsh - left shift accumulator by known count                  */
8495 /*-----------------------------------------------------------------*/
8496 static void AccLsh (int shCount, int doMask)
8497 {
8498         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8499         switch(shCount){
8500                 case 0 :
8501                         return;
8502                         break;
8503                 case 1 :
8504                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505                         break;
8506                 case 2 :
8507                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8508                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8509                         break;
8510                 case 3 :
8511                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8512                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         break;
8514                 case 4 :
8515                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8516                         break;
8517                 case 5 :
8518                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8519                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520                         break;
8521                 case 6 :
8522                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         break;
8525                 case 7 :
8526                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527                         break;
8528         }
8529         if (doMask) {
8530                 /* no masking is required in genPackBits */
8531                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8532         }
8533 }
8534
8535 /*-----------------------------------------------------------------*/
8536 /* AccRsh - right shift accumulator by known count                 */
8537 /*-----------------------------------------------------------------*/
8538 static void AccRsh (int shCount, int andmask)
8539 {
8540         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8541         switch(shCount){
8542                 case 0 :
8543                         return; break;
8544                 case 1 :
8545                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8546                         break;
8547                 case 2 :
8548                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8549                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8550                         break;
8551                 case 3 :
8552                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8554                         break;
8555                 case 4 :
8556                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         break;
8558                 case 5 :
8559                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561                         break;
8562                 case 6 :
8563                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         break;
8566                 case 7 :
8567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569         }
8570         
8571         if(andmask)
8572                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8573         else
8574                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8575 }
8576
8577 #if 0
8578 /*-----------------------------------------------------------------*/
8579 /* AccSRsh - signed right shift accumulator by known count                 */
8580 /*-----------------------------------------------------------------*/
8581 static void AccSRsh (int shCount)
8582 {
8583     symbol *tlbl ;
8584     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8585     if(shCount != 0){
8586         if(shCount == 1){
8587             pic16_emitcode("mov","c,acc.7");
8588             pic16_emitcode("rrc","a");
8589         } else if(shCount == 2){
8590             pic16_emitcode("mov","c,acc.7");
8591             pic16_emitcode("rrc","a");
8592             pic16_emitcode("mov","c,acc.7");
8593             pic16_emitcode("rrc","a");
8594         } else {
8595             tlbl = newiTempLabel(NULL);
8596             /* rotate right accumulator */
8597             AccRol(8 - shCount);
8598             /* and kill the higher order bits */
8599             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8600             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8601             pic16_emitcode("orl","a,#0x%02x",
8602                      (unsigned char)~SRMask[shCount]);
8603             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8604         }
8605     }
8606 }
8607 #endif
8608
8609 /*-----------------------------------------------------------------*/
8610 /* shiftR1Left2Result - shift right one byte from left to result   */
8611 /*-----------------------------------------------------------------*/
8612 static void shiftR1Left2ResultSigned (operand *left, int offl,
8613                                 operand *result, int offr,
8614                                 int shCount)
8615 {
8616   int same;
8617
8618   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8619
8620   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8621
8622   switch(shCount) {
8623   case 1:
8624     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8625     if(same) 
8626       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8627     else {
8628       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8629       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8630     }
8631
8632     break;
8633   case 2:
8634
8635     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8636     if(same) 
8637       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8638     else {
8639       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8640       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8641     }
8642     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8643     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8644
8645     break;
8646
8647   case 3:
8648     if(same)
8649       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8650     else {
8651       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8652       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8653     }
8654
8655     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8656     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8657     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8658
8659     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8660     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8661
8662     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8663     break;
8664
8665   case 4:
8666     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8667     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8668     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8669     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8670     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8671     break;
8672   case 5:
8673     if(same) {
8674       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8675     } else {
8676       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8677       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8678     }
8679     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8680     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8681     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8682     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8683     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8684     break;
8685
8686   case 6:
8687     if(same) {
8688       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8689       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8690       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8691       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8692       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8693       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8694     } else {
8695       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8696       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8697       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8698       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8699       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8700     }
8701     break;
8702
8703   case 7:
8704     if(same) {
8705       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8706       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8707       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8708       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709     } else {
8710       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8711       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8712       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8713     }
8714
8715   default:
8716     break;
8717   }
8718 }
8719
8720 /*-----------------------------------------------------------------*/
8721 /* shiftR1Left2Result - shift right one byte from left to result   */
8722 /*-----------------------------------------------------------------*/
8723 static void shiftR1Left2Result (operand *left, int offl,
8724                                 operand *result, int offr,
8725                                 int shCount, int sign)
8726 {
8727   int same;
8728
8729   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8730
8731   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8732
8733   /* Copy the msb into the carry if signed. */
8734   if(sign) {
8735     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8736     return;
8737   }
8738
8739
8740
8741   switch(shCount) {
8742   case 1:
8743     emitCLRC;
8744     if(same) 
8745       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8746     else {
8747       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8748       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8749     }
8750     break;
8751   case 2:
8752     emitCLRC;
8753     if(same) {
8754       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8755     } else {
8756       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8757       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8758     }
8759     emitCLRC;
8760     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8761
8762     break;
8763   case 3:
8764     if(same)
8765       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8766     else {
8767       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8768       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8769     }
8770
8771     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8772     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8773     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8774     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8775     break;
8776       
8777   case 4:
8778     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8779     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8780     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781     break;
8782
8783   case 5:
8784     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8785     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8786     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787     //emitCLRC;
8788     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8789
8790     break;
8791   case 6:
8792
8793     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8794     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8795     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8796     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8797     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8798     break;
8799
8800   case 7:
8801
8802     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8803     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8804     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8805
8806     break;
8807
8808   default:
8809     break;
8810   }
8811 }
8812
8813 /*-----------------------------------------------------------------*/
8814 /* shiftL1Left2Result - shift left one byte from left to result    */
8815 /*-----------------------------------------------------------------*/
8816 static void shiftL1Left2Result (operand *left, int offl,
8817                                 operand *result, int offr, int shCount)
8818 {
8819   int same;
8820
8821   //    char *l;
8822   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8823
8824   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8825   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8826     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8827     //    MOVA(l);
8828     /* shift left accumulator */
8829     //AccLsh(shCount, 1); // don't comment out just yet...
8830   //    pic16_aopPut(AOP(result),"a",offr);
8831
8832   switch(shCount) {
8833   case 1:
8834     /* Shift left 1 bit position */
8835     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8836     if(same) {
8837       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8838     } else {
8839       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8840       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8841     }
8842     break;
8843   case 2:
8844     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8845     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8846     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8847     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8848     break;
8849   case 3:
8850     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8851     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8852     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8853     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8854     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8855     break;
8856   case 4:
8857     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8858     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8859     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860     break;
8861   case 5:
8862     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8863     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8864     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8866     break;
8867   case 6:
8868     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8869     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8870     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8871     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8872     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8873     break;
8874   case 7:
8875     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8876     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8877     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8878     break;
8879
8880   default:
8881     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8882   }
8883
8884 }
8885
8886 /*-----------------------------------------------------------------*/
8887 /* movLeft2Result - move byte from left to result                  */
8888 /*-----------------------------------------------------------------*/
8889 static void movLeft2Result (operand *left, int offl,
8890                             operand *result, int offr)
8891 {
8892   char *l;
8893   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8894   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8895     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8896
8897     if (*l == '@' && (IS_AOP_PREG(result))) {
8898       pic16_emitcode("mov","a,%s",l);
8899       pic16_aopPut(AOP(result),"a",offr);
8900     } else {
8901       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8902       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8903     }
8904   }
8905 }
8906
8907 /*-----------------------------------------------------------------*/
8908 /* shiftL2Left2Result - shift left two bytes from left to result   */
8909 /*-----------------------------------------------------------------*/
8910 static void shiftL2Left2Result (operand *left, int offl,
8911                                 operand *result, int offr, int shCount)
8912 {
8913   int same = pic16_sameRegs(AOP(result), AOP(left));
8914   int i;
8915
8916   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8917
8918   if (same && (offl != offr)) { // shift bytes
8919     if (offr > offl) {
8920        for(i=1;i>-1;i--) {
8921          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8922          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8923        }
8924     } else { // just treat as different later on
8925                 same = 0;
8926     }
8927   }
8928
8929   if(same) {
8930     switch(shCount) {
8931     case 0:
8932       break;
8933     case 1:
8934     case 2:
8935     case 3:
8936
8937       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8938       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8939       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8940
8941       while(--shCount) {
8942                 emitCLRC;
8943                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8944                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8945       }
8946
8947       break;
8948     case 4:
8949     case 5:
8950       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8951       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8952       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8953       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8955       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8956       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8957       if(shCount >=5) {
8958                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8960       }
8961       break;
8962     case 6:
8963       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8964       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8965       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8968       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8969       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973       break;
8974     case 7:
8975       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8976       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8977       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8980     }
8981
8982   } else {
8983     switch(shCount) {
8984     case 0:
8985       break;
8986     case 1:
8987     case 2:
8988     case 3:
8989       /* note, use a mov/add for the shift since the mov has a
8990          chance of getting optimized out */
8991       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8992       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8993       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8994       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8995       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8996
8997       while(--shCount) {
8998                 emitCLRC;
8999                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9000                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9001       }
9002       break;
9003
9004     case 4:
9005     case 5:
9006       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9007       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9009       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9010       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9011       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9012       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9013       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9014
9015
9016       if(shCount == 5) {
9017                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9018                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9019       }
9020       break;
9021     case 6:
9022       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9023       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9025       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9026
9027       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9028       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9030       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9031       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9032       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9033       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9035       break;
9036     case 7:
9037       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9041       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9042     }
9043   }
9044
9045 }
9046 /*-----------------------------------------------------------------*/
9047 /* shiftR2Left2Result - shift right two bytes from left to result  */
9048 /*-----------------------------------------------------------------*/
9049 static void shiftR2Left2Result (operand *left, int offl,
9050                                 operand *result, int offr,
9051                                 int shCount, int sign)
9052 {
9053   int same = pic16_sameRegs(AOP(result), AOP(left));
9054   int i;
9055   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9056
9057   if (same && (offl != offr)) { // shift right bytes
9058     if (offr < offl) {
9059        for(i=0;i<2;i++) {
9060          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9061          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9062        }
9063     } else { // just treat as different later on
9064                 same = 0;
9065     }
9066   }
9067
9068   switch(shCount) {
9069   case 0:
9070     break;
9071   case 1:
9072   case 2:
9073   case 3:
9074     if(sign)
9075       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9076     else
9077       emitCLRC;
9078
9079     if(same) {
9080       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9081       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9082     } else {
9083       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9084       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9085       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9086       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9087     }
9088
9089     while(--shCount) {
9090       if(sign)
9091                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9092       else
9093                 emitCLRC;
9094       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9095       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9096     }
9097     break;
9098   case 4:
9099   case 5:
9100     if(same) {
9101
9102       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9103       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9104       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9105
9106       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9107       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9108       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9109       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9110     } else {
9111       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9112       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9113       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9114
9115       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9116       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9117       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9118       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9119       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9120     }
9121
9122     if(shCount >=5) {
9123       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9124       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9125     }
9126
9127     if(sign) {
9128       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9129       pic16_emitpcode(POC_BTFSC, 
9130                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9131       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9132     }
9133
9134     break;
9135
9136   case 6:
9137     if(same) {
9138
9139       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9140       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9141
9142       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9143       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9144       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9145       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9146       if(sign) {
9147         pic16_emitpcode(POC_BTFSC, 
9148                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9149         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9150       }
9151       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9152       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9153       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9154       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9155     } else {
9156       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9157       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9158       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9159       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9160       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9162       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9163       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9164       if(sign) {
9165         pic16_emitpcode(POC_BTFSC, 
9166                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9167         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9168       }
9169       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9170       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9171
9172         
9173     }
9174
9175     break;
9176   case 7:
9177     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9178     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9179     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9180     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9181     if(sign) {
9182       emitSKPNC;
9183       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9184     } else 
9185       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9186   }
9187 }
9188
9189
9190 /*-----------------------------------------------------------------*/
9191 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9192 /*-----------------------------------------------------------------*/
9193 static void shiftLLeftOrResult (operand *left, int offl,
9194                                 operand *result, int offr, int shCount)
9195 {
9196     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9197
9198     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9199     /* shift left accumulator */
9200     AccLsh(shCount, 1);
9201     /* or with result */
9202     /* back to result */
9203     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9204 }
9205
9206 /*-----------------------------------------------------------------*/
9207 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9208 /*-----------------------------------------------------------------*/
9209 static void shiftRLeftOrResult (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 right accumulator */
9216     AccRsh(shCount, 1);
9217     /* or with result */
9218     /* back to result */
9219     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9220 }
9221
9222 /*-----------------------------------------------------------------*/
9223 /* genlshOne - left shift a one byte quantity by known count       */
9224 /*-----------------------------------------------------------------*/
9225 static void genlshOne (operand *result, operand *left, int shCount)
9226 {       
9227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9228     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9229 }
9230
9231 /*-----------------------------------------------------------------*/
9232 /* genlshTwo - left shift two bytes by known amount != 0           */
9233 /*-----------------------------------------------------------------*/
9234 static void genlshTwo (operand *result,operand *left, int shCount)
9235 {
9236     int size;
9237     
9238     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9239     size = pic16_getDataSize(result);
9240
9241     /* if shCount >= 8 */
9242     if (shCount >= 8) {
9243         shCount -= 8 ;
9244
9245         if (size > 1){
9246             if (shCount)
9247                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9248             else 
9249                 movLeft2Result(left, LSB, result, MSB16);
9250         }
9251         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9252     }
9253
9254     /*  1 <= shCount <= 7 */
9255     else {  
9256         if(size == 1)
9257             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9258         else 
9259             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9260     }
9261 }
9262
9263 /*-----------------------------------------------------------------*/
9264 /* shiftLLong - shift left one long from left to result            */
9265 /* offr = LSB or MSB16                                             */
9266 /*-----------------------------------------------------------------*/
9267 static void shiftLLong (operand *left, operand *result, int offr )
9268 {
9269     int size = AOP_SIZE(result);
9270     int same = pic16_sameRegs(AOP(left),AOP(result));
9271         int i;
9272
9273     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9274
9275         if (same && (offr == MSB16)) { //shift one byte
9276                 for(i=size-1;i>=MSB16;i--) {
9277                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9278                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9279                 }
9280         } else {
9281                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9282         }
9283         
9284     if (size > LSB+offr ){
9285                 if (same) {
9286                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9287                 } else {
9288                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9289                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9290                 }
9291          }
9292
9293     if(size > MSB16+offr){
9294                 if (same) {
9295                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9296                 } else {
9297                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9298                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9299                 }
9300     }
9301
9302     if(size > MSB24+offr){
9303                 if (same) {
9304                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9305                 } else {
9306                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9307                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9308                 }
9309     }
9310
9311     if(size > MSB32+offr){
9312                 if (same) {
9313                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9314                 } else {
9315                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9316                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9317                 }
9318     }
9319     if(offr != LSB)
9320                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9321
9322 }
9323
9324 /*-----------------------------------------------------------------*/
9325 /* genlshFour - shift four byte by a known amount != 0             */
9326 /*-----------------------------------------------------------------*/
9327 static void genlshFour (operand *result, operand *left, int shCount)
9328 {
9329     int size;
9330
9331     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9332     size = AOP_SIZE(result);
9333
9334     /* if shifting more that 3 bytes */
9335     if (shCount >= 24 ) {
9336         shCount -= 24;
9337         if (shCount)
9338             /* lowest order of left goes to the highest
9339             order of the destination */
9340             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9341         else
9342             movLeft2Result(left, LSB, result, MSB32);
9343
9344                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9345                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9346                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9347
9348         return;
9349     }
9350
9351     /* more than two bytes */
9352     else if ( shCount >= 16 ) {
9353         /* lower order two bytes goes to higher order two bytes */
9354         shCount -= 16;
9355         /* if some more remaining */
9356         if (shCount)
9357             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9358         else {
9359             movLeft2Result(left, MSB16, result, MSB32);
9360             movLeft2Result(left, LSB, result, MSB24);
9361         }
9362                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9363                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9364         return;
9365     }    
9366
9367     /* if more than 1 byte */
9368     else if ( shCount >= 8 ) {
9369         /* lower order three bytes goes to higher order  three bytes */
9370         shCount -= 8;
9371         if(size == 2){
9372             if(shCount)
9373                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9374             else
9375                 movLeft2Result(left, LSB, result, MSB16);
9376         }
9377         else{   /* size = 4 */
9378             if(shCount == 0){
9379                 movLeft2Result(left, MSB24, result, MSB32);
9380                 movLeft2Result(left, MSB16, result, MSB24);
9381                 movLeft2Result(left, LSB, result, MSB16);
9382                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9383             }
9384             else if(shCount == 1)
9385                 shiftLLong(left, result, MSB16);
9386             else{
9387                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9388                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9389                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9390                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9391             }
9392         }
9393     }
9394
9395     /* 1 <= shCount <= 7 */
9396     else if(shCount <= 3)
9397     { 
9398         shiftLLong(left, result, LSB);
9399         while(--shCount >= 1)
9400             shiftLLong(result, result, LSB);
9401     }
9402     /* 3 <= shCount <= 7, optimize */
9403     else{
9404         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9405         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9406         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9407     }
9408 }
9409
9410 /*-----------------------------------------------------------------*/
9411 /* genLeftShiftLiteral - left shifting by known count              */
9412 /*-----------------------------------------------------------------*/
9413 void pic16_genLeftShiftLiteral (operand *left,
9414                                  operand *right,
9415                                  operand *result,
9416                                  iCode *ic)
9417 {    
9418     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9419     int size;
9420
9421     FENTRY;
9422     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9423     pic16_freeAsmop(right,NULL,ic,TRUE);
9424
9425     pic16_aopOp(left,ic,FALSE);
9426     pic16_aopOp(result,ic,TRUE);
9427
9428     size = getSize(operandType(result));
9429
9430 #if VIEW_SIZE
9431     pic16_emitcode("; shift left ","result %d, left %d",size,
9432              AOP_SIZE(left));
9433 #endif
9434
9435     /* I suppose that the left size >= result size */
9436     if(shCount == 0){
9437         while(size--){
9438             movLeft2Result(left, size, result, size);
9439         }
9440     }
9441
9442     else if(shCount >= (size * 8))
9443         while(size--)
9444             pic16_aopPut(AOP(result),zero,size);
9445     else{
9446         switch (size) {
9447             case 1:
9448                 genlshOne (result,left,shCount);
9449                 break;
9450
9451             case 2:
9452             case 3:
9453                 genlshTwo (result,left,shCount);
9454                 break;
9455
9456             case 4:
9457                 genlshFour (result,left,shCount);
9458                 break;
9459         }
9460     }
9461     pic16_freeAsmop(left,NULL,ic,TRUE);
9462     pic16_freeAsmop(result,NULL,ic,TRUE);
9463 }
9464
9465 /*-----------------------------------------------------------------*
9466  * genMultiAsm - repeat assembly instruction for size of register.
9467  * if endian == 1, then the high byte (i.e base address + size of 
9468  * register) is used first else the low byte is used first;
9469  *-----------------------------------------------------------------*/
9470 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9471 {
9472
9473   int offset = 0;
9474
9475   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9476
9477   if(!reg)
9478     return;
9479
9480   if(!endian) {
9481     endian = 1;
9482   } else {
9483     endian = -1;
9484     offset = size-1;
9485   }
9486
9487   while(size--) {
9488     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9489     offset += endian;
9490   }
9491
9492 }
9493
9494 #if !(USE_GENERIC_SIGNED_SHIFT)
9495 /*-----------------------------------------------------------------*/
9496 /* genLeftShift - generates code for left shifting                 */
9497 /*-----------------------------------------------------------------*/
9498 static void genLeftShift (iCode *ic)
9499 {
9500   operand *left,*right, *result;
9501   int size, offset;
9502 //  char *l;
9503   symbol *tlbl , *tlbl1;
9504   pCodeOp *pctemp;
9505
9506   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9507
9508   right = IC_RIGHT(ic);
9509   left  = IC_LEFT(ic);
9510   result = IC_RESULT(ic);
9511
9512   pic16_aopOp(right,ic,FALSE);
9513
9514   /* if the shift count is known then do it 
9515      as efficiently as possible */
9516   if (AOP_TYPE(right) == AOP_LIT) {
9517     pic16_genLeftShiftLiteral (left,right,result,ic);
9518     return ;
9519   }
9520
9521   /* shift count is unknown then we have to form
9522    * a loop. Get the loop count in WREG : Note: we take
9523    * only the lower order byte since shifting
9524    * more than 32 bits make no sense anyway, ( the
9525    * largest size of an object can be only 32 bits ) */
9526   
9527   pic16_aopOp(left,ic,FALSE);
9528   pic16_aopOp(result,ic,FALSE);
9529
9530   /* now move the left to the result if they are not the
9531    * same, and if size > 1,
9532    * and if right is not same to result (!!!) -- VR */
9533   if (!pic16_sameRegs(AOP(left),AOP(result))
9534       && (AOP_SIZE(result) > 1)) {
9535
9536     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9537
9538     size = AOP_SIZE(result);
9539     offset=0;
9540     while (size--) {
9541
9542 #if 0
9543       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9544       if (*l == '@' && (IS_AOP_PREG(result))) {
9545
9546           pic16_emitcode("mov","a,%s",l);
9547           pic16_aopPut(AOP(result),"a",offset);
9548       } else
9549 #endif
9550       {
9551         /* we don't know if left is a literal or a register, take care -- VR */
9552         pic16_mov2f(AOP(result), AOP(left), offset);
9553       }
9554       offset++;
9555     }
9556   }
9557
9558   size = AOP_SIZE(result);
9559
9560   /* if it is only one byte then */
9561   if (size == 1) {
9562     if(optimized_for_speed) {
9563       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9564       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9565       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9566       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9567       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9568       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9569       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9570       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9571       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9572       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9573       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9574       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9575     } else {
9576
9577       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9578
9579       tlbl = newiTempLabel(NULL);
9580
9581 #if 1
9582       /* this is already done, why change it? */
9583       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9584                 pic16_mov2f(AOP(result), AOP(left), 0);
9585       }
9586 #endif
9587
9588       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9589       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9590       pic16_emitpLabel(tlbl->key);
9591       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9592       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9593       emitSKPC;
9594       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9595     }
9596     goto release ;
9597   }
9598     
9599   if (pic16_sameRegs(AOP(left),AOP(result))) {
9600
9601     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9602     
9603     tlbl = newiTempLabel(NULL);
9604     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9605     genMultiAsm(POC_RRCF, result, size,1);
9606     pic16_emitpLabel(tlbl->key);
9607     genMultiAsm(POC_RLCF, result, size,0);
9608     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9609     emitSKPC;
9610     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9611     goto release;
9612   }
9613
9614   //tlbl = newiTempLabel(NULL);
9615   //offset = 0 ;   
9616   //tlbl1 = newiTempLabel(NULL);
9617
9618   //reAdjustPreg(AOP(result));    
9619     
9620   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9621   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9622   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9623   //MOVA(l);
9624   //pic16_emitcode("add","a,acc");         
9625   //pic16_aopPut(AOP(result),"a",offset++);
9626   //while (--size) {
9627   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9628   //  MOVA(l);
9629   //  pic16_emitcode("rlc","a");         
9630   //  pic16_aopPut(AOP(result),"a",offset++);
9631   //}
9632   //reAdjustPreg(AOP(result));
9633
9634   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9635   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9636
9637
9638   tlbl = newiTempLabel(NULL);
9639   tlbl1= newiTempLabel(NULL);
9640
9641   size = AOP_SIZE(result);
9642   offset = 1;
9643
9644   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9645
9646   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9647
9648   /* offset should be 0, 1 or 3 */
9649   
9650   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9651   emitSKPNZ;
9652   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9653
9654   pic16_emitpcode(POC_MOVWF, pctemp);
9655
9656
9657   pic16_emitpLabel(tlbl->key);
9658
9659   emitCLRC;
9660   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9661   while(--size)
9662     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9663
9664   pic16_emitpcode(POC_DECFSZ,  pctemp);
9665   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9666   pic16_emitpLabel(tlbl1->key);
9667
9668   pic16_popReleaseTempReg(pctemp,1);
9669
9670
9671  release:
9672   pic16_freeAsmop (right,NULL,ic,TRUE);
9673   pic16_freeAsmop(left,NULL,ic,TRUE);
9674   pic16_freeAsmop(result,NULL,ic,TRUE);
9675 }
9676 #endif
9677
9678
9679 #if 0
9680 #error old code (left here for reference)
9681 /*-----------------------------------------------------------------*/
9682 /* genLeftShift - generates code for left shifting                 */
9683 /*-----------------------------------------------------------------*/
9684 static void genLeftShift (iCode *ic)
9685 {
9686   operand *left,*right, *result;
9687   int size, offset;
9688   char *l;
9689   symbol *tlbl , *tlbl1;
9690   pCodeOp *pctemp;
9691
9692   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9693
9694   right = IC_RIGHT(ic);
9695   left  = IC_LEFT(ic);
9696   result = IC_RESULT(ic);
9697
9698   pic16_aopOp(right,ic,FALSE);
9699
9700   /* if the shift count is known then do it 
9701      as efficiently as possible */
9702   if (AOP_TYPE(right) == AOP_LIT) {
9703     pic16_genLeftShiftLiteral (left,right,result,ic);
9704     return ;
9705   }
9706
9707   /* shift count is unknown then we have to form 
9708      a loop get the loop count in B : Note: we take
9709      only the lower order byte since shifting
9710      more that 32 bits make no sense anyway, ( the
9711      largest size of an object can be only 32 bits ) */  
9712
9713     
9714   pic16_aopOp(left,ic,FALSE);
9715   pic16_aopOp(result,ic,FALSE);
9716
9717   /* now move the left to the result if they are not the
9718      same */
9719   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9720       AOP_SIZE(result) > 1) {
9721
9722     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9723
9724     size = AOP_SIZE(result);
9725     offset=0;
9726     while (size--) {
9727       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9728       if (*l == '@' && (IS_AOP_PREG(result))) {
9729
9730         pic16_emitcode("mov","a,%s",l);
9731         pic16_aopPut(AOP(result),"a",offset);
9732       } else {
9733
9734         /* we don't know if left is a literal or a register, take care -- VR */
9735         pic16_mov2f(AOP(result), AOP(left), offset);
9736       }
9737       offset++;
9738     }
9739   }
9740
9741   size = AOP_SIZE(result);
9742
9743   /* if it is only one byte then */
9744   if (size == 1) {
9745     if(optimized_for_speed) {
9746       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9747       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9748       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9749       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9750       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9751       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9752       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9753       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9754       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9755       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9756       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9757       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9758     } else {
9759
9760       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9761
9762       tlbl = newiTempLabel(NULL);
9763       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9764                 pic16_mov2f(AOP(result), AOP(left), 0);
9765                 
9766 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9767 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9768       }
9769
9770       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9771       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9772       pic16_emitpLabel(tlbl->key);
9773       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9774       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9775       emitSKPC;
9776       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9777     }
9778     goto release ;
9779   }
9780     
9781   if (pic16_sameRegs(AOP(left),AOP(result))) {
9782
9783     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9784     
9785     tlbl = newiTempLabel(NULL);
9786     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9787     genMultiAsm(POC_RRCF, result, size,1);
9788     pic16_emitpLabel(tlbl->key);
9789     genMultiAsm(POC_RLCF, result, size,0);
9790     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9791     emitSKPC;
9792     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9793     goto release;
9794   }
9795
9796   //tlbl = newiTempLabel(NULL);
9797   //offset = 0 ;   
9798   //tlbl1 = newiTempLabel(NULL);
9799
9800   //reAdjustPreg(AOP(result));    
9801     
9802   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9803   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9804   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9805   //MOVA(l);
9806   //pic16_emitcode("add","a,acc");         
9807   //pic16_aopPut(AOP(result),"a",offset++);
9808   //while (--size) {
9809   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9810   //  MOVA(l);
9811   //  pic16_emitcode("rlc","a");         
9812   //  pic16_aopPut(AOP(result),"a",offset++);
9813   //}
9814   //reAdjustPreg(AOP(result));
9815
9816   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9817   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9818
9819
9820   tlbl = newiTempLabel(NULL);
9821   tlbl1= newiTempLabel(NULL);
9822
9823   size = AOP_SIZE(result);
9824   offset = 1;
9825
9826   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9827
9828   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9829
9830   /* offset should be 0, 1 or 3 */
9831   
9832   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9833   emitSKPNZ;
9834   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9835
9836   pic16_emitpcode(POC_MOVWF, pctemp);
9837
9838
9839   pic16_emitpLabel(tlbl->key);
9840
9841   emitCLRC;
9842   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9843   while(--size)
9844     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9845
9846   pic16_emitpcode(POC_DECFSZ,  pctemp);
9847   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9848   pic16_emitpLabel(tlbl1->key);
9849
9850   pic16_popReleaseTempReg(pctemp,1);
9851
9852
9853  release:
9854   pic16_freeAsmop (right,NULL,ic,TRUE);
9855   pic16_freeAsmop(left,NULL,ic,TRUE);
9856   pic16_freeAsmop(result,NULL,ic,TRUE);
9857 }
9858 #endif
9859
9860 /*-----------------------------------------------------------------*/
9861 /* genrshOne - right shift a one byte quantity by known count      */
9862 /*-----------------------------------------------------------------*/
9863 static void genrshOne (operand *result, operand *left,
9864                        int shCount, int sign)
9865 {
9866     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9867     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9868 }
9869
9870 /*-----------------------------------------------------------------*/
9871 /* genrshTwo - right shift two bytes by known amount != 0          */
9872 /*-----------------------------------------------------------------*/
9873 static void genrshTwo (operand *result,operand *left,
9874                        int shCount, int sign)
9875 {
9876   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9877   /* if shCount >= 8 */
9878   if (shCount >= 8) {
9879     shCount -= 8 ;
9880     if (shCount)
9881       shiftR1Left2Result(left, MSB16, result, LSB,
9882                          shCount, sign);
9883     else
9884       movLeft2Result(left, MSB16, result, LSB);
9885
9886     pic16_addSign (result, 1, sign);
9887   }
9888
9889   /*  1 <= shCount <= 7 */
9890   else
9891     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9892 }
9893
9894 /*-----------------------------------------------------------------*/
9895 /* shiftRLong - shift right one long from left to result           */
9896 /* offl = LSB or MSB16                                             */
9897 /*-----------------------------------------------------------------*/
9898 static void shiftRLong (operand *left, int offl,
9899                         operand *result, int sign)
9900 {
9901     int size = AOP_SIZE(result);
9902     int same = pic16_sameRegs(AOP(left),AOP(result));
9903     int i;
9904     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9905
9906         if (same && (offl == MSB16)) { //shift one byte right
9907                 for(i=MSB16;i<size;i++) {
9908                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9909                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9910                 }
9911         }
9912
9913     if(sign)
9914                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9915         else
9916                 emitCLRC;
9917
9918         if (same) {
9919                 if (offl == LSB)
9920                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9921         } else {
9922         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9923         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9924         }
9925
9926     if(offl == MSB16) {
9927         /* add sign of "a" */
9928         pic16_addSign(result, MSB32, sign);
9929         }
9930
9931         if (same) {
9932         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9933         } else {
9934         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9935         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9936         }
9937         
9938         if (same) {
9939         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9940         } else {
9941         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9942         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9943         }
9944
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9947         } else {
9948         if(offl == LSB){
9949                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9950                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9951         }
9952         }
9953 }
9954
9955 /*-----------------------------------------------------------------*/
9956 /* genrshFour - shift four byte by a known amount != 0             */
9957 /*-----------------------------------------------------------------*/
9958 static void genrshFour (operand *result, operand *left,
9959                         int shCount, int sign)
9960 {
9961   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9962   /* if shifting more that 3 bytes */
9963   if(shCount >= 24 ) {
9964     shCount -= 24;
9965     if(shCount)
9966       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9967     else
9968       movLeft2Result(left, MSB32, result, LSB);
9969
9970     pic16_addSign(result, MSB16, sign);
9971   }
9972   else if(shCount >= 16){
9973     shCount -= 16;
9974     if(shCount)
9975       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9976     else{
9977       movLeft2Result(left, MSB24, result, LSB);
9978       movLeft2Result(left, MSB32, result, MSB16);
9979     }
9980     pic16_addSign(result, MSB24, sign);
9981   }
9982   else if(shCount >= 8){
9983     shCount -= 8;
9984     if(shCount == 1)
9985       shiftRLong(left, MSB16, result, sign);
9986     else if(shCount == 0){
9987       movLeft2Result(left, MSB16, result, LSB);
9988       movLeft2Result(left, MSB24, result, MSB16);
9989       movLeft2Result(left, MSB32, result, MSB24);
9990       pic16_addSign(result, MSB32, sign);
9991     }
9992     else{ //shcount >= 2
9993       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9994       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9995       /* the last shift is signed */
9996       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9997       pic16_addSign(result, MSB32, sign);
9998     }
9999   }
10000   else{   /* 1 <= shCount <= 7 */
10001     if(shCount <= 2){
10002       shiftRLong(left, LSB, result, sign);
10003       if(shCount == 2)
10004         shiftRLong(result, LSB, result, sign);
10005     }
10006     else{
10007       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10008       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10009       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10010     }
10011   }
10012 }
10013
10014 /*-----------------------------------------------------------------*/
10015 /* genRightShiftLiteral - right shifting by known count            */
10016 /*-----------------------------------------------------------------*/
10017 static void genRightShiftLiteral (operand *left,
10018                                   operand *right,
10019                                   operand *result,
10020                                   iCode *ic,
10021                                   int sign)
10022 {    
10023   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10024   int lsize,res_size;
10025
10026   pic16_freeAsmop(right,NULL,ic,TRUE);
10027
10028   pic16_aopOp(left,ic,FALSE);
10029   pic16_aopOp(result,ic,TRUE);
10030
10031   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10032
10033 #if VIEW_SIZE
10034   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10035                  AOP_SIZE(left));
10036 #endif
10037
10038   lsize = pic16_getDataSize(left);
10039   res_size = pic16_getDataSize(result);
10040   /* test the LEFT size !!! */
10041
10042   /* I suppose that the left size >= result size */
10043   if(shCount == 0){
10044     assert (res_size <= lsize);
10045     while (res_size--) {
10046       pic16_mov2f (AOP(result), AOP(left), res_size);
10047     } // for
10048   }
10049
10050   else if(shCount >= (lsize * 8)){
10051
10052     if(res_size == 1) {
10053       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10054       if(sign) {
10055         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10056         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10057       }
10058     } else {
10059
10060       if(sign) {
10061         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10062         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10064         while(res_size--)
10065           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10066
10067       } else {
10068
10069         while(res_size--)
10070           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10071       }
10072     }
10073   } else {
10074
10075     switch (res_size) {
10076     case 1:
10077       genrshOne (result,left,shCount,sign);
10078       break;
10079
10080     case 2:
10081       genrshTwo (result,left,shCount,sign);
10082       break;
10083
10084     case 4:
10085       genrshFour (result,left,shCount,sign);
10086       break;
10087     default :
10088       break;
10089     }
10090
10091   }
10092
10093   pic16_freeAsmop(left,NULL,ic,TRUE);
10094   pic16_freeAsmop(result,NULL,ic,TRUE);
10095 }
10096
10097 #if !(USE_GENERIC_SIGNED_SHIFT)
10098 /*-----------------------------------------------------------------*/
10099 /* genSignedRightShift - right shift of signed number              */
10100 /*-----------------------------------------------------------------*/
10101 static void genSignedRightShift (iCode *ic)
10102 {
10103   operand *right, *left, *result;
10104   int size, offset;
10105   //  char *l;
10106   symbol *tlbl, *tlbl1 ;
10107   pCodeOp *pctemp;
10108
10109   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10110
10111   /* we do it the hard way put the shift count in b
10112      and loop thru preserving the sign */
10113   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10114
10115   right = IC_RIGHT(ic);
10116   left  = IC_LEFT(ic);
10117   result = IC_RESULT(ic);
10118
10119   pic16_aopOp(right,ic,FALSE);  
10120   pic16_aopOp(left,ic,FALSE);
10121   pic16_aopOp(result,ic,FALSE);
10122
10123
10124   if ( AOP_TYPE(right) == AOP_LIT) {
10125     genRightShiftLiteral (left,right,result,ic,1);
10126     return ;
10127   }
10128   /* shift count is unknown then we have to form 
10129      a loop get the loop count in B : Note: we take
10130      only the lower order byte since shifting
10131      more that 32 bits make no sense anyway, ( the
10132      largest size of an object can be only 32 bits ) */  
10133
10134   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10135   //pic16_emitcode("inc","b");
10136   //pic16_freeAsmop (right,NULL,ic,TRUE);
10137   //pic16_aopOp(left,ic,FALSE);
10138   //pic16_aopOp(result,ic,FALSE);
10139
10140   /* now move the left to the result if they are not the
10141      same */
10142   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10143       AOP_SIZE(result) > 1) {
10144
10145     size = AOP_SIZE(result);
10146     offset=0;
10147     while (size--) { 
10148       /*
10149         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10150         if (*l == '@' && IS_AOP_PREG(result)) {
10151
10152         pic16_emitcode("mov","a,%s",l);
10153         pic16_aopPut(AOP(result),"a",offset);
10154         } else
10155         pic16_aopPut(AOP(result),l,offset);
10156       */
10157       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10158       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10159
10160       offset++;
10161     }
10162   }
10163
10164   /* mov the highest order bit to OVR */    
10165   tlbl = newiTempLabel(NULL);
10166   tlbl1= newiTempLabel(NULL);
10167
10168   size = AOP_SIZE(result);
10169   offset = size - 1;
10170
10171   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10172
10173   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10174
10175   /* offset should be 0, 1 or 3 */
10176   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10177   emitSKPNZ;
10178   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10179
10180   pic16_emitpcode(POC_MOVWF, pctemp);
10181
10182
10183   pic16_emitpLabel(tlbl->key);
10184
10185   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10186   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10187
10188   while(--size) {
10189     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10190   }
10191
10192   pic16_emitpcode(POC_DECFSZ,  pctemp);
10193   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10194   pic16_emitpLabel(tlbl1->key);
10195
10196   pic16_popReleaseTempReg(pctemp,1);
10197 #if 0
10198   size = AOP_SIZE(result);
10199   offset = size - 1;
10200   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10201   pic16_emitcode("rlc","a");
10202   pic16_emitcode("mov","ov,c");
10203   /* if it is only one byte then */
10204   if (size == 1) {
10205     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10206     MOVA(l);
10207     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10208     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10209     pic16_emitcode("mov","c,ov");
10210     pic16_emitcode("rrc","a");
10211     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10212     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10213     pic16_aopPut(AOP(result),"a",0);
10214     goto release ;
10215   }
10216
10217   reAdjustPreg(AOP(result));
10218   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10219   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10220   pic16_emitcode("mov","c,ov");
10221   while (size--) {
10222     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10223     MOVA(l);
10224     pic16_emitcode("rrc","a");         
10225     pic16_aopPut(AOP(result),"a",offset--);
10226   }
10227   reAdjustPreg(AOP(result));
10228   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10229   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10230
10231  release:
10232 #endif
10233
10234   pic16_freeAsmop(left,NULL,ic,TRUE);
10235   pic16_freeAsmop(result,NULL,ic,TRUE);
10236   pic16_freeAsmop(right,NULL,ic,TRUE);
10237 }
10238 #endif
10239
10240 #if !(USE_GENERIC_SIGNED_SHIFT)
10241 #warning This implementation of genRightShift() is incomplete!
10242 /*-----------------------------------------------------------------*/
10243 /* genRightShift - generate code for right shifting                */
10244 /*-----------------------------------------------------------------*/
10245 static void genRightShift (iCode *ic)
10246 {
10247     operand *right, *left, *result;
10248     sym_link *letype ;
10249     int size, offset;
10250     char *l;
10251     symbol *tlbl, *tlbl1 ;
10252
10253     /* if signed then we do it the hard way preserve the
10254     sign bit moving it inwards */
10255     letype = getSpec(operandType(IC_LEFT(ic)));
10256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10257
10258     if (!SPEC_USIGN(letype)) {
10259         genSignedRightShift (ic);
10260         return ;
10261     }
10262
10263     /* signed & unsigned types are treated the same : i.e. the
10264     signed is NOT propagated inwards : quoting from the
10265     ANSI - standard : "for E1 >> E2, is equivalent to division
10266     by 2**E2 if unsigned or if it has a non-negative value,
10267     otherwise the result is implementation defined ", MY definition
10268     is that the sign does not get propagated */
10269
10270     right = IC_RIGHT(ic);
10271     left  = IC_LEFT(ic);
10272     result = IC_RESULT(ic);
10273
10274     pic16_aopOp(right,ic,FALSE);
10275
10276     /* if the shift count is known then do it 
10277     as efficiently as possible */
10278     if (AOP_TYPE(right) == AOP_LIT) {
10279         genRightShiftLiteral (left,right,result,ic, 0);
10280         return ;
10281     }
10282
10283     /* shift count is unknown then we have to form 
10284     a loop get the loop count in B : Note: we take
10285     only the lower order byte since shifting
10286     more that 32 bits make no sense anyway, ( the
10287     largest size of an object can be only 32 bits ) */  
10288
10289     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10290     pic16_emitcode("inc","b");
10291     pic16_aopOp(left,ic,FALSE);
10292     pic16_aopOp(result,ic,FALSE);
10293
10294     /* now move the left to the result if they are not the
10295     same */
10296     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10297         AOP_SIZE(result) > 1) {
10298
10299         size = AOP_SIZE(result);
10300         offset=0;
10301         while (size--) {
10302             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10303             if (*l == '@' && IS_AOP_PREG(result)) {
10304
10305                 pic16_emitcode("mov","a,%s",l);
10306                 pic16_aopPut(AOP(result),"a",offset);
10307             } else
10308                 pic16_aopPut(AOP(result),l,offset);
10309             offset++;
10310         }
10311     }
10312
10313     tlbl = newiTempLabel(NULL);
10314     tlbl1= newiTempLabel(NULL);
10315     size = AOP_SIZE(result);
10316     offset = size - 1;
10317
10318     /* if it is only one byte then */
10319     if (size == 1) {
10320
10321       tlbl = newiTempLabel(NULL);
10322       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10323         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10324         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10325       }
10326
10327       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10328       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10329       pic16_emitpLabel(tlbl->key);
10330       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10331       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10332       emitSKPC;
10333       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10334
10335       goto release ;
10336     }
10337
10338     reAdjustPreg(AOP(result));
10339     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10340     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10341     CLRC;
10342     while (size--) {
10343         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10344         MOVA(l);
10345         pic16_emitcode("rrc","a");         
10346         pic16_aopPut(AOP(result),"a",offset--);
10347     }
10348     reAdjustPreg(AOP(result));
10349
10350     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10351     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10352
10353 release:
10354     pic16_freeAsmop(left,NULL,ic,TRUE);
10355     pic16_freeAsmop (right,NULL,ic,TRUE);
10356     pic16_freeAsmop(result,NULL,ic,TRUE);
10357 }
10358 #endif
10359
10360 #if (USE_GENERIC_SIGNED_SHIFT)
10361 /*-----------------------------------------------------------------*/
10362 /* genGenericShift - generates code for left or right shifting     */
10363 /*-----------------------------------------------------------------*/
10364 static void genGenericShift (iCode *ic, int isShiftLeft) {
10365   operand *left,*right, *result;
10366   int offset;
10367   int sign, signedCount;
10368   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10369   PIC_OPCODE pos_shift, neg_shift;
10370
10371   FENTRY;
10372
10373   right = IC_RIGHT(ic);
10374   left  = IC_LEFT(ic);
10375   result = IC_RESULT(ic);
10376
10377   pic16_aopOp(right,ic,FALSE);
10378   pic16_aopOp(left,ic,FALSE);
10379   pic16_aopOp(result,ic,TRUE);
10380
10381   sign = !SPEC_USIGN(operandType (left));
10382   signedCount = !SPEC_USIGN(operandType (right));
10383
10384   /* if the shift count is known then do it 
10385      as efficiently as possible */
10386   if (AOP_TYPE(right) == AOP_LIT) {
10387     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10388     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10389     // we should modify right->aopu.aop_lit here!
10390     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10391     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10392     if (isShiftLeft)
10393       pic16_genLeftShiftLiteral (left,right,result,ic);
10394     else
10395       genRightShiftLiteral (left,right,result,ic, sign);
10396
10397     goto release;
10398   } // if (right is literal)
10399
10400   /* shift count is unknown then we have to form a loop.
10401    * Note: we take only the lower order byte since shifting
10402    * more than 32 bits make no sense anyway, ( the
10403    * largest size of an object can be only 32 bits )
10404    * Note: we perform arithmetic shifts if the left operand is
10405    * signed and we do an (effective) right shift, i. e. we
10406    * shift in the sign bit from the left. */
10407    
10408   label_complete = newiTempLabel ( NULL );
10409   label_loop_pos = newiTempLabel ( NULL );
10410   label_loop_neg = NULL;
10411   label_negative = NULL;
10412   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10413   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10414
10415   if (signedCount) {
10416     // additional labels needed
10417     label_loop_neg = newiTempLabel ( NULL );
10418     label_negative = newiTempLabel ( NULL );
10419   } // if
10420
10421   // copy source to result -- this will effectively truncate the left operand to the size of result!
10422   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10423   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10424   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10425     pic16_mov2f (AOP(result),AOP(left), offset);
10426   } // for
10427
10428   // if result is longer than left, fill with zeros (or sign)
10429   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10430     if (sign && AOP_SIZE(left) > 0) {
10431       // shift signed operand -- fill with sign
10432       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10433       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10434       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10435       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10436         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10437       } // for
10438     } else {
10439       // shift unsigned operand -- fill result with zeros
10440       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10441         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10442       } // for
10443     }
10444   } // if (size mismatch)
10445
10446   pic16_mov2w (AOP(right), 0);
10447   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10448   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10449   
10450 #if 0
10451   // perform a shift by one (shift count is positive)
10452   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10453   // 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])
10454   pic16_emitpLabel (label_loop_pos->key);
10455   emitCLRC;
10456   if (sign && (pos_shift == POC_RRCF)) {
10457     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10458     emitSETC;
10459   } // if
10460   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10461   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10462   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10463 #else
10464   // perform a shift by one (shift count is positive)
10465   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10466   // 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])
10467   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10468   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10469   emitCLRC;
10470   pic16_emitpLabel (label_loop_pos->key);
10471   if (sign && (pos_shift == POC_RRCF)) {
10472     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10473     emitSETC;
10474   } // if
10475   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10476   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10477   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10478   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10479 #endif
10480
10481   if (signedCount) {
10482     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10483
10484     pic16_emitpLabel (label_negative->key);
10485     // perform a shift by -1 (shift count is negative)
10486     // 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)
10487     emitCLRC;
10488     pic16_emitpLabel (label_loop_neg->key);
10489     if (sign && (neg_shift == POC_RRCF)) {
10490       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10491       emitSETC;
10492     } // if
10493     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10494     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10495     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10496     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10497   } // if (signedCount)
10498
10499   pic16_emitpLabel (label_complete->key);
10500
10501 release:
10502   pic16_freeAsmop (right,NULL,ic,TRUE);
10503   pic16_freeAsmop(left,NULL,ic,TRUE);
10504   pic16_freeAsmop(result,NULL,ic,TRUE);
10505 }
10506
10507 static void genLeftShift (iCode *ic) {
10508   genGenericShift (ic, 1);
10509 }
10510
10511 static void genRightShift (iCode *ic) {
10512   genGenericShift (ic, 0);
10513 }
10514 #endif
10515
10516
10517 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10518 void pic16_loadFSR0(operand *op, int lit)
10519 {
10520   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10521     if (AOP_TYPE(op) == AOP_LIT) {
10522       /* handle 12 bit integers correctly */
10523       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10524       if ((val & 0x0fff) != val) {
10525         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10526                 val, (val & 0x0fff) );
10527         val &= 0x0fff;
10528       }
10529       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10530     } else {
10531       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10532     }
10533   } else {
10534     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10535     // set up FSR0 with address of result
10536     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10537     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10538   }
10539 }
10540
10541 /*----------------------------------------------------------------*/
10542 /* pic16_derefPtr - move one byte from the location ptr points to */
10543 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10544 /*                  to the location ptr points to (doWrite != 0)   */
10545 /*----------------------------------------------------------------*/
10546 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10547 {
10548   if (!IS_PTR(operandType(ptr)))
10549   {
10550     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10551     else pic16_mov2w (AOP(ptr), 0);
10552     return;
10553   }
10554
10555   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10556   /* We might determine pointer type right here: */
10557   p_type = DCL_TYPE(operandType(ptr));
10558
10559   switch (p_type) {
10560     case FPOINTER:
10561     case POINTER:
10562       if (!fsr0_setup || !*fsr0_setup)
10563       {
10564         pic16_loadFSR0( ptr, 0 );
10565         if (fsr0_setup) *fsr0_setup = 1;
10566       }
10567       if (doWrite)
10568         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10569       else
10570         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10571       break;
10572
10573     case GPOINTER:
10574       if (AOP(ptr)->aopu.aop_reg[2]) {
10575         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10576         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10577         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10578         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10579         pic16_mov2w(AOP(ptr), 2);
10580         pic16_callGenericPointerRW(doWrite, 1);
10581       } else {
10582         // data pointer (just 2 byte given)
10583         if (!fsr0_setup || !*fsr0_setup)
10584         {
10585           pic16_loadFSR0( ptr, 0 );
10586           if (fsr0_setup) *fsr0_setup = 1;
10587         }
10588         if (doWrite)
10589           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10590         else
10591           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10592       }
10593       break;
10594
10595     default:
10596       assert (0 && "invalid pointer type specified");
10597       break;
10598   }
10599 }
10600
10601 /*-----------------------------------------------------------------*/
10602 /* genUnpackBits - generates code for unpacking bits               */
10603 /*-----------------------------------------------------------------*/
10604 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10605 {    
10606   int shCnt ;
10607   sym_link *etype, *letype;
10608   int blen=0, bstr=0;
10609   int lbstr;
10610   int same;
10611   pCodeOp *op;
10612
10613   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10614   etype = getSpec(operandType(result));
10615   letype = getSpec(operandType(left));
10616
10617   //    if(IS_BITFIELD(etype)) {
10618   blen = SPEC_BLEN(etype);
10619   bstr = SPEC_BSTR(etype);
10620   //    }
10621
10622   lbstr = SPEC_BSTR( letype );
10623
10624   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10625       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10626
10627 #if 1
10628   if((blen == 1) && (bstr < 8)
10629       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10630     /* it is a single bit, so use the appropriate bit instructions */
10631     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10632
10633     same = pic16_sameRegs(AOP(left),AOP(result));
10634     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10635     pic16_emitpcode(POC_CLRF, op);
10636
10637     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10638       /* workaround to reduce the extra lfsr instruction */
10639       pic16_emitpcode(POC_BTFSC,
10640           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10641     } else {
10642       assert (PIC_IS_DATA_PTR (operandType(left)));
10643       pic16_loadFSR0 (left, 0);
10644       pic16_emitpcode(POC_BTFSC,
10645           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10646     }
10647
10648     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10649       /* unsigned bitfields result in either 0 or 1 */
10650       pic16_emitpcode(POC_INCF, op);
10651     } else {
10652       /* signed bitfields result in either 0 or -1 */
10653       pic16_emitpcode(POC_DECF, op);
10654     }
10655     if (same) {
10656       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10657     }
10658
10659     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10660     return;
10661   }
10662
10663 #endif
10664
10665   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10666     // access symbol directly
10667     pic16_mov2w (AOP(left), 0);
10668   } else {
10669     pic16_derefPtr (left, ptype, 0, NULL);
10670   }
10671
10672   /* if we have bitdisplacement then it fits   */
10673   /* into this byte completely or if length is */
10674   /* less than a byte                          */
10675   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10676
10677     /* shift right acc */
10678     AccRsh(shCnt, 0);
10679
10680     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10681           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10682
10683     /* VR -- normally I would use the following, but since we use the hack,
10684      * to avoid the masking from AccRsh, why not mask it right now? */
10685
10686     /*
10687        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10688      */
10689
10690     /* extend signed bitfields to 8 bits */
10691     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10692     {
10693       assert (blen + bstr > 0);
10694       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10695       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10696     }
10697
10698     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10699
10700     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10701     return ;
10702   }
10703
10704   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10705   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10706   exit(-1);
10707
10708   return ;
10709 }
10710
10711
10712 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10713 {
10714   int size, offset = 0, leoffset=0 ;
10715
10716         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10717         pic16_aopOp(result, ic, TRUE);
10718
10719         FENTRY;
10720
10721         size = AOP_SIZE(result);
10722 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10723
10724
10725 #if 1
10726         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10727                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10728                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10729                 goto release;
10730         }
10731 #endif
10732
10733         if(AOP(left)->aopu.pcop->type == PO_DIR)
10734                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10735
10736         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10737
10738         while (size--) {
10739                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10740                 
10741 //              pic16_DumpOp("(result)",result);
10742                 if(is_LitAOp(AOP(result))) {
10743                         pic16_mov2w(AOP(left), offset); // patch 8
10744                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10745                 } else {
10746                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10747                                 pic16_popGet(AOP(left), offset), //patch 8
10748                                 pic16_popGet(AOP(result), offset)));
10749                 }
10750
10751                 offset++;
10752                 leoffset++;
10753         }
10754
10755 release:
10756     pic16_freeAsmop(result,NULL,ic,TRUE);
10757 }
10758
10759
10760
10761 /*-----------------------------------------------------------------*/
10762 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10763 /*-----------------------------------------------------------------*/
10764 static void genNearPointerGet (operand *left, 
10765                                operand *result, 
10766                                iCode *ic)
10767 {
10768 //  asmop *aop = NULL;
10769   //regs *preg = NULL ;
10770   sym_link *rtype, *retype;
10771   sym_link *ltype, *letype;
10772
10773     FENTRY;
10774     
10775     rtype = operandType(result);
10776     retype= getSpec(rtype);
10777     ltype = operandType(left);
10778     letype= getSpec(ltype);
10779     
10780     pic16_aopOp(left,ic,FALSE);
10781
10782 //    pic16_DumpOp("(left)",left);
10783 //    pic16_DumpOp("(result)",result);
10784
10785     /* if left is rematerialisable and
10786      * result is not bit variable type and
10787      * the left is pointer to data space i.e
10788      * lower 128 bytes of space */
10789     
10790     if (AOP_TYPE(left) == AOP_PCODE
10791       && !IS_BITFIELD(retype)
10792       && DCL_TYPE(ltype) == POINTER) {
10793
10794         genDataPointerGet (left,result,ic);
10795         pic16_freeAsmop(left, NULL, ic, TRUE);
10796         return ;
10797     }
10798     
10799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10800     pic16_aopOp (result,ic,TRUE);
10801     
10802     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10803
10804 #if 1
10805     if(IS_BITFIELD( retype )
10806       && (SPEC_BLEN(operandType(result))==1)
10807     ) {
10808       iCode *nextic;
10809       pCodeOp *jop;
10810       int bitstrt, bytestrt;
10811
10812         /* if this is bitfield of size 1, see if we are checking the value
10813          * of a single bit in an if-statement,
10814          * if yes, then don't generate usual code, but execute the
10815          * genIfx directly -- VR */
10816
10817         nextic = ic->next;
10818
10819         /* CHECK: if next iCode is IFX
10820          * and current result operand is nextic's conditional operand
10821          * and current result operand live ranges ends at nextic's key number
10822          */
10823         if((nextic->op == IFX)
10824           && (result == IC_COND(nextic))
10825           && (OP_LIVETO(result) == nextic->seq)
10826           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10827           ) {
10828             /* everything is ok then */
10829             /* find a way to optimize the genIfx iCode */
10830
10831             bytestrt = SPEC_BSTR(operandType(result))/8;
10832             bitstrt = SPEC_BSTR(operandType(result))%8;
10833             
10834             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10835
10836             genIfxpCOpJump(nextic, jop);
10837             
10838             pic16_freeAsmop(left, NULL, ic, TRUE);
10839             pic16_freeAsmop(result, NULL, ic, TRUE);
10840             return;
10841         }
10842     }
10843 #endif
10844
10845     /* if bitfield then unpack the bits */
10846     if (IS_BITFIELD(letype)) 
10847       genUnpackBits (result, left, NULL, POINTER);
10848     else {
10849       /* we have can just get the values */
10850       int size = AOP_SIZE(result);
10851       int offset = 0;   
10852         
10853       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10854
10855       pic16_loadFSR0( left, 0 );
10856
10857       while(size--) {
10858         if(size) {
10859           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10860                 pic16_popGet(AOP(result), offset++)));
10861         } else {
10862           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10863                 pic16_popGet(AOP(result), offset++)));
10864         }
10865       }
10866     }
10867
10868 #if 0
10869     /* now some housekeeping stuff */
10870     if (aop) {
10871       /* we had to allocate for this iCode */
10872       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10873       pic16_freeAsmop(NULL,aop,ic,TRUE);
10874     } else { 
10875       /* we did not allocate which means left
10876        * already in a pointer register, then
10877        * if size > 0 && this could be used again
10878        * we have to point it back to where it 
10879        * belongs */
10880       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10881       if (AOP_SIZE(result) > 1
10882         && !OP_SYMBOL(left)->remat
10883         && ( OP_SYMBOL(left)->liveTo > ic->seq
10884             || ic->depth )) {
10885 //        int size = AOP_SIZE(result) - 1;
10886 //        while (size--)
10887 //          pic16_emitcode("dec","%s",rname);
10888         }
10889     }
10890 #endif
10891
10892     /* done */
10893     pic16_freeAsmop(left,NULL,ic,TRUE);
10894     pic16_freeAsmop(result,NULL,ic,TRUE);
10895 }
10896
10897 /*-----------------------------------------------------------------*/
10898 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10899 /*-----------------------------------------------------------------*/
10900 static void genPagedPointerGet (operand *left, 
10901                                operand *result, 
10902                                iCode *ic)
10903 {
10904     asmop *aop = NULL;
10905     regs *preg = NULL ;
10906     char *rname ;
10907     sym_link *rtype, *retype;    
10908
10909     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10910
10911     rtype = operandType(result);
10912     retype= getSpec(rtype);
10913     
10914     pic16_aopOp(left,ic,FALSE);
10915
10916   /* if the value is already in a pointer register
10917        then don't need anything more */
10918     if (!AOP_INPREG(AOP(left))) {
10919         /* otherwise get a free pointer register */
10920         aop = newAsmop(0);
10921         preg = getFreePtr(ic,&aop,FALSE);
10922         pic16_emitcode("mov","%s,%s",
10923                 preg->name,
10924                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10925         rname = preg->name ;
10926     } else
10927         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10928     
10929     pic16_freeAsmop(left,NULL,ic,TRUE);
10930     pic16_aopOp (result,ic,TRUE);
10931
10932     /* if bitfield then unpack the bits */
10933     if (IS_BITFIELD(retype)) 
10934         genUnpackBits (result,left,rname,PPOINTER);
10935     else {
10936         /* we have can just get the values */
10937         int size = AOP_SIZE(result);
10938         int offset = 0 ;        
10939         
10940         while (size--) {
10941             
10942             pic16_emitcode("movx","a,@%s",rname);
10943             pic16_aopPut(AOP(result),"a",offset);
10944             
10945             offset++ ;
10946             
10947             if (size)
10948                 pic16_emitcode("inc","%s",rname);
10949         }
10950     }
10951
10952     /* now some housekeeping stuff */
10953     if (aop) {
10954         /* we had to allocate for this iCode */
10955         pic16_freeAsmop(NULL,aop,ic,TRUE);
10956     } else { 
10957         /* we did not allocate which means left
10958            already in a pointer register, then
10959            if size > 0 && this could be used again
10960            we have to point it back to where it 
10961            belongs */
10962         if (AOP_SIZE(result) > 1 &&
10963             !OP_SYMBOL(left)->remat &&
10964             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10965               ic->depth )) {
10966             int size = AOP_SIZE(result) - 1;
10967             while (size--)
10968                 pic16_emitcode("dec","%s",rname);
10969         }
10970     }
10971
10972     /* done */
10973     pic16_freeAsmop(result,NULL,ic,TRUE);
10974     
10975         
10976 }
10977
10978 #if 0
10979 /* This code is not adjusted to PIC16 and fails utterly.
10980  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10981
10982 /*-----------------------------------------------------------------*/
10983 /* genFarPointerGet - gget value from far space                    */
10984 /*-----------------------------------------------------------------*/
10985 static void genFarPointerGet (operand *left,
10986                               operand *result, iCode *ic)
10987 {
10988     int size, offset ;
10989     sym_link *retype = getSpec(operandType(result));
10990
10991     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10992
10993     pic16_aopOp(left,ic,FALSE);
10994
10995     /* if the operand is already in dptr 
10996     then we do nothing else we move the value to dptr */
10997     if (AOP_TYPE(left) != AOP_STR) {
10998         /* if this is remateriazable */
10999         if (AOP_TYPE(left) == AOP_IMMD)
11000             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11001         else { /* we need to get it byte by byte */
11002             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11003             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11004             if (options.model == MODEL_FLAT24)
11005             {
11006                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11007             }
11008         }
11009     }
11010     /* so dptr know contains the address */
11011     pic16_freeAsmop(left,NULL,ic,TRUE);
11012     pic16_aopOp(result,ic,TRUE);
11013
11014     /* if bit then unpack */
11015     if (IS_BITFIELD(retype)) 
11016         genUnpackBits(result,left,"dptr",FPOINTER);
11017     else {
11018         size = AOP_SIZE(result);
11019         offset = 0 ;
11020
11021         while (size--) {
11022             pic16_emitcode("movx","a,@dptr");
11023             pic16_aopPut(AOP(result),"a",offset++);
11024             if (size)
11025                 pic16_emitcode("inc","dptr");
11026         }
11027     }
11028
11029     pic16_freeAsmop(result,NULL,ic,TRUE);
11030 }
11031 #endif
11032
11033 #if 0
11034 /*-----------------------------------------------------------------*/
11035 /* genCodePointerGet - get value from code space                  */
11036 /*-----------------------------------------------------------------*/
11037 static void genCodePointerGet (operand *left,
11038                                 operand *result, iCode *ic)
11039 {
11040     int size, offset ;
11041     sym_link *retype = getSpec(operandType(result));
11042
11043     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11044
11045     pic16_aopOp(left,ic,FALSE);
11046
11047     /* if the operand is already in dptr 
11048     then we do nothing else we move the value to dptr */
11049     if (AOP_TYPE(left) != AOP_STR) {
11050         /* if this is remateriazable */
11051         if (AOP_TYPE(left) == AOP_IMMD)
11052             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11053         else { /* we need to get it byte by byte */
11054             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11055             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11056             if (options.model == MODEL_FLAT24)
11057             {
11058                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11059             }
11060         }
11061     }
11062     /* so dptr know contains the address */
11063     pic16_freeAsmop(left,NULL,ic,TRUE);
11064     pic16_aopOp(result,ic,FALSE);
11065
11066     /* if bit then unpack */
11067     if (IS_BITFIELD(retype)) 
11068         genUnpackBits(result,left,"dptr",CPOINTER);
11069     else {
11070         size = AOP_SIZE(result);
11071         offset = 0 ;
11072
11073         while (size--) {
11074             pic16_emitcode("clr","a");
11075             pic16_emitcode("movc","a,@a+dptr");
11076             pic16_aopPut(AOP(result),"a",offset++);
11077             if (size)
11078                 pic16_emitcode("inc","dptr");
11079         }
11080     }
11081
11082     pic16_freeAsmop(result,NULL,ic,TRUE);
11083 }
11084 #endif
11085
11086 #if 0
11087 /*-----------------------------------------------------------------*/
11088 /* genGenPointerGet - gget value from generic pointer space        */
11089 /*-----------------------------------------------------------------*/
11090 static void genGenPointerGet (operand *left,
11091                               operand *result, iCode *ic)
11092 {
11093   int size, offset, lit;
11094   sym_link *retype = getSpec(operandType(result));
11095
11096         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11097         pic16_aopOp(left,ic,FALSE);
11098         pic16_aopOp(result,ic,FALSE);
11099         size = AOP_SIZE(result);
11100
11101         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11102
11103         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11104
11105                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11106                 // load FSR0 from immediate
11107                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11108
11109 //              pic16_loadFSR0( left );
11110
11111                 offset = 0;
11112                 while(size--) {
11113                         if(size) {
11114                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11115                         } else {
11116                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11117                         }
11118                         offset++;
11119                 }
11120                 goto release;
11121
11122         }
11123         else { /* we need to get it byte by byte */
11124                 // set up FSR0 with address from left
11125                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11126                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11127                 
11128                 offset = 0 ;
11129
11130                 while(size--) {
11131                         if(size) {
11132                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11133                         } else {
11134                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11135                         }
11136                         offset++;
11137                 }
11138                 goto release;
11139         }
11140
11141   /* if bit then unpack */
11142         if (IS_BITFIELD(retype)) 
11143                 genUnpackBits(result,left,"BAD",GPOINTER);
11144
11145         release:
11146         pic16_freeAsmop(left,NULL,ic,TRUE);
11147         pic16_freeAsmop(result,NULL,ic,TRUE);
11148
11149 }
11150 #endif
11151
11152
11153 /*-----------------------------------------------------------------*/
11154 /* genGenPointerGet - gget value from generic pointer space        */
11155 /*-----------------------------------------------------------------*/
11156 static void genGenPointerGet (operand *left,
11157                               operand *result, iCode *ic)
11158 {
11159   int size, offset, lit;
11160   sym_link *letype = getSpec(operandType(left));
11161
11162     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11163     pic16_aopOp(left,ic,FALSE);
11164     pic16_aopOp(result,ic,TRUE);
11165     size = AOP_SIZE(result);
11166
11167     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11168   
11169     /* if bit then unpack */
11170     if (IS_BITFIELD(letype)) {
11171       genUnpackBits(result,left,"BAD",GPOINTER);
11172       goto release;
11173     }
11174
11175     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11176
11177       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11178       // load FSR0 from immediate
11179       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11180
11181       werror(W_POSSBUG2, __FILE__, __LINE__);
11182
11183       offset = 0;
11184       while(size--) {
11185         if(size) {
11186           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11187         } else {
11188           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11189         }
11190         offset++;
11191       }
11192
11193       goto release;
11194
11195     } else { /* we need to get it byte by byte */
11196
11197       /* set up WREG:PRODL:FSR0L with address from left */
11198       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11199       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11200       pic16_mov2w(AOP(left), 2);
11201       pic16_callGenericPointerRW(0, size);
11202       
11203       assignResultValue(result, 1);
11204       
11205       goto release;
11206     }
11207
11208 release:
11209   pic16_freeAsmop(left,NULL,ic,TRUE);
11210   pic16_freeAsmop(result,NULL,ic,TRUE);
11211 }
11212
11213 /*-----------------------------------------------------------------*/
11214 /* genConstPointerGet - get value from const generic pointer space */
11215 /*-----------------------------------------------------------------*/
11216 static void genConstPointerGet (operand *left,
11217                                 operand *result, iCode *ic)
11218 {
11219   //sym_link *retype = getSpec(operandType(result));
11220   // symbol *albl = newiTempLabel(NULL);        // patch 15
11221   // symbol *blbl = newiTempLabel(NULL);        //
11222   // PIC_OPCODE poc;                            // patch 15
11223   int size;
11224   int offset = 0;
11225
11226   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11227   pic16_aopOp(left,ic,FALSE);
11228   pic16_aopOp(result,ic,TRUE);
11229   size = AOP_SIZE(result);
11230
11231   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11232
11233   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11234
11235   // set up table pointer
11236   if( (AOP_TYPE(left) == AOP_PCODE) 
11237       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11238           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11239     {
11240       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11241       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11242       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11243       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11244       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11245       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11246   } else {
11247     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11248     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11249     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11250   }
11251
11252   while(size--) {
11253     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11254     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11255     offset++;
11256   }
11257     
11258   pic16_freeAsmop(left,NULL,ic,TRUE);
11259   pic16_freeAsmop(result,NULL,ic,TRUE);
11260 }
11261
11262
11263 /*-----------------------------------------------------------------*/
11264 /* genPointerGet - generate code for pointer get                   */
11265 /*-----------------------------------------------------------------*/
11266 static void genPointerGet (iCode *ic)
11267 {
11268   operand *left, *result ;
11269   sym_link *type, *etype;
11270   int p_type;
11271
11272     FENTRY;
11273     
11274     left = IC_LEFT(ic);
11275     result = IC_RESULT(ic) ;
11276
11277     /* depending on the type of pointer we need to
11278     move it to the correct pointer register */
11279     type = operandType(left);
11280     etype = getSpec(type);
11281
11282 #if 0
11283     if (IS_PTR_CONST(type))
11284 #else
11285     if (IS_CODEPTR(type))
11286 #endif
11287       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11288
11289     /* if left is of type of pointer then it is simple */
11290     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11291       p_type = DCL_TYPE(type);
11292     else {
11293       /* we have to go by the storage class */
11294       p_type = PTR_TYPE(SPEC_OCLS(etype));
11295
11296       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11297
11298       if (SPEC_OCLS(etype)->codesp ) {
11299         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11300         //p_type = CPOINTER ;   
11301       } else
11302       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11303         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11304         /*p_type = FPOINTER ;*/ 
11305       } else
11306       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11307         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11308         /* p_type = PPOINTER; */
11309       } else
11310       if (SPEC_OCLS(etype) == idata ) {
11311         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11312         /* p_type = IPOINTER; */
11313       } else {
11314         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11315         /* p_type = POINTER ; */
11316       }
11317     }
11318
11319     /* now that we have the pointer type we assign
11320     the pointer values */
11321     switch (p_type) {
11322       case POINTER:     
11323       case FPOINTER:
11324       case IPOINTER:
11325         genNearPointerGet (left,result,ic);
11326         break;
11327
11328       case PPOINTER:
11329         genPagedPointerGet(left,result,ic);
11330         break;
11331
11332 #if 0
11333       /* PICs do not support FAR pointers... */
11334       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11335       case FPOINTER:
11336         genFarPointerGet (left,result,ic);
11337         break;
11338 #endif
11339
11340       case CPOINTER:
11341         genConstPointerGet (left,result,ic);
11342         //pic16_emitcodePointerGet (left,result,ic);
11343         break;
11344
11345       case GPOINTER:
11346 #if 0
11347       if (IS_PTR_CONST(type))
11348         genConstPointerGet (left,result,ic);
11349       else
11350 #endif
11351         genGenPointerGet (left,result,ic);
11352       break;
11353
11354     default:
11355       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11356               "genPointerGet: illegal pointer type");
11357     
11358     }
11359 }
11360
11361 /*-----------------------------------------------------------------*/
11362 /* genPackBits - generates code for packed bit storage             */
11363 /*-----------------------------------------------------------------*/
11364 static void genPackBits (sym_link    *etype , operand *result,
11365                          operand *right ,
11366                          char *rname, int p_type)
11367 {
11368   int shCnt = 0 ;
11369   int offset = 0  ;
11370   int rLen = 0 ;
11371   int blen, bstr ;   
11372   int shifted_and_masked = 0;
11373   unsigned long lit = (unsigned long)-1;
11374   sym_link *retype;
11375
11376   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11377   blen = SPEC_BLEN(etype);
11378   bstr = SPEC_BSTR(etype);
11379
11380   retype = getSpec(operandType(right));
11381
11382   if(AOP_TYPE(right) == AOP_LIT) {
11383     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11384     
11385     if((blen == 1) && (bstr < 8)) {
11386       /* it is a single bit, so use the appropriate bit instructions */
11387
11388       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11389
11390       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11391         /* workaround to reduce the extra lfsr instruction */
11392         if(lit) {
11393           pic16_emitpcode(POC_BSF,
11394               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11395         } else {
11396           pic16_emitpcode(POC_BCF,
11397               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11398         }
11399       } else {
11400         if (PIC_IS_DATA_PTR(operandType(result))) {
11401           pic16_loadFSR0(result, 0);
11402           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11403               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11404         } else {
11405           /* get old value */
11406           pic16_derefPtr (result, p_type, 0, NULL);
11407           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11408               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11409           /* write back new value */
11410           pic16_derefPtr (result, p_type, 1, NULL);
11411         }
11412       }
11413
11414       return;
11415     }
11416     /* IORLW below is more efficient */
11417     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11418     lit = (lit & ((1UL << blen) - 1)) << bstr;
11419     shifted_and_masked = 1;
11420     offset++;
11421   } else
11422     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11423         && IS_BITFIELD(retype) 
11424         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11425         && (blen == 1)) {
11426       int rblen, rbstr;
11427
11428       rblen = SPEC_BLEN( retype );
11429       rbstr = SPEC_BSTR( retype );
11430
11431       if(IS_BITFIELD(etype)) {
11432         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11433         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11434       } else {
11435         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11436       }
11437
11438       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11439
11440       if(IS_BITFIELD(etype)) {
11441         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11442       } else {
11443         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11444       }
11445
11446       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11447
11448       return;
11449     } else {
11450       /* move right to W */
11451       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11452     }
11453
11454   /* if the bit length is less than or   */
11455   /* it exactly fits a byte then         */
11456   if((shCnt=SPEC_BSTR(etype))
11457       || SPEC_BLEN(etype) <= 8 )  {
11458     int fsr0_setup = 0;
11459
11460     if (blen != 8 || bstr != 0) {
11461       // we need to combine the value with the old value
11462       if(!shifted_and_masked)
11463       {
11464         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11465
11466         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11467             SPEC_BSTR(etype), SPEC_BLEN(etype));
11468
11469         /* shift left acc, do NOT mask the result again */
11470         AccLsh(shCnt, 0);
11471
11472         /* using PRODH as a temporary register here */
11473         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11474       }
11475
11476       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11477         || IS_DIRECT(result)) {
11478         /* access symbol directly */
11479         pic16_mov2w (AOP(result), 0);
11480       } else {
11481         /* get old value */
11482         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11483       }
11484 #if 1
11485       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11486             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11487                             (unsigned char)(0xff >> (8-bstr))) ));
11488       if (!shifted_and_masked) {
11489         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11490       } else {
11491         /* We have the shifted and masked (literal) right value in `lit' */
11492         if (lit != 0)
11493           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11494       }
11495     } // if (blen != 8 || bstr != 0)
11496
11497     /* write new value back */
11498     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11499         || IS_DIRECT(result)) {
11500       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11501     } else {
11502       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11503     }
11504 #endif
11505
11506     return;
11507   }
11508
11509
11510 #if 0
11511   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11512   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11513   exit(-1);
11514 #endif
11515
11516
11517   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11518   rLen = SPEC_BLEN(etype)-8;
11519
11520   /* now generate for lengths greater than one byte */
11521   while (1) {
11522     rLen -= 8 ;
11523     if (rLen <= 0 ) {
11524       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11525       break ;
11526     }
11527
11528     switch (p_type) {
11529       case POINTER:
11530         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11531         break;
11532
11533         /*
11534            case FPOINTER:
11535            MOVA(l);
11536            pic16_emitcode("movx","@dptr,a");
11537            break;
11538
11539            case GPOINTER:
11540            MOVA(l);
11541            DEBUGpic16_emitcode(";lcall","__gptrput");
11542            break;  
11543          */
11544       default:
11545         assert(0);
11546     }   
11547
11548
11549     pic16_mov2w(AOP(right), offset++);
11550   }
11551
11552   /* last last was not complete */
11553   if (rLen)   {
11554     /* save the byte & read byte */
11555     switch (p_type) {
11556       case POINTER:
11557         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11558         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11559         break;
11560
11561         /*
11562            case FPOINTER:
11563            pic16_emitcode ("mov","b,a");
11564            pic16_emitcode("movx","a,@dptr");
11565            break;
11566
11567            case GPOINTER:
11568            pic16_emitcode ("push","b");
11569            pic16_emitcode ("push","acc");
11570            pic16_emitcode ("lcall","__gptrget");
11571            pic16_emitcode ("pop","b");
11572            break;
11573          */
11574       default:
11575         assert(0);
11576     }
11577     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11578     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11579     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11580     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11581     //        pic16_emitcode ("orl","a,b");
11582   }
11583
11584   //    if (p_type == GPOINTER)
11585   //        pic16_emitcode("pop","b");
11586
11587   switch (p_type) {
11588
11589     case POINTER:
11590       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11591       //        pic16_emitcode("mov","@%s,a",rname);
11592       break;
11593       /*
11594          case FPOINTER:
11595          pic16_emitcode("movx","@dptr,a");
11596          break;
11597
11598          case GPOINTER:
11599          DEBUGpic16_emitcode(";lcall","__gptrput");
11600          break;                 
11601        */
11602     default:
11603       assert(0);
11604   }
11605
11606   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11607 }
11608
11609 /*-----------------------------------------------------------------*/
11610 /* genDataPointerSet - remat pointer to data space                 */
11611 /*-----------------------------------------------------------------*/
11612 static void genDataPointerSet(operand *right,
11613                               operand *result,
11614                               iCode *ic)
11615 {
11616   int size, offset = 0, resoffset=0 ;
11617
11618     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11619     pic16_aopOp(right,ic,FALSE);
11620
11621     size = AOP_SIZE(right);
11622
11623 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11624
11625 #if 0
11626     if ( AOP_TYPE(result) == AOP_PCODE) {
11627       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11628               AOP(result)->aopu.pcop->name,
11629                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11630               PCOR(AOP(result)->aopu.pcop)->instance:
11631               PCOI(AOP(result)->aopu.pcop)->offset);
11632     }
11633 #endif
11634
11635     if(AOP(result)->aopu.pcop->type == PO_DIR)
11636       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11637
11638     while (size--) {
11639       if (AOP_TYPE(right) == AOP_LIT) {
11640         unsigned int lit;
11641
11642           if(!IS_FLOAT(operandType( right )))
11643             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11644           else {
11645             union {
11646               unsigned long lit_int;
11647               float lit_float;
11648             } info;
11649         
11650               /* take care if literal is a float */
11651               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11652               lit = info.lit_int;
11653           }
11654                     lit = lit >> (8*offset);
11655                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11656                 } else {
11657                   pic16_mov2w(AOP(right), offset);
11658                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11659                 }
11660                 offset++;
11661                 resoffset++;
11662         }
11663
11664     pic16_freeAsmop(right,NULL,ic,TRUE);
11665 }
11666
11667
11668
11669 /*-----------------------------------------------------------------*/
11670 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11671 /*-----------------------------------------------------------------*/
11672 static void genNearPointerSet (operand *right,
11673                                operand *result, 
11674                                iCode *ic)
11675 {
11676   asmop *aop = NULL;
11677   sym_link *retype;
11678   sym_link *ptype = operandType(result);
11679   sym_link *resetype;
11680     
11681     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11682     retype= getSpec(operandType(right));
11683     resetype = getSpec(operandType(result));
11684   
11685     pic16_aopOp(result,ic,FALSE);
11686     
11687     /* if the result is rematerializable &
11688      * in data space & not a bit variable */
11689         
11690     /* and result is not a bit variable */
11691     if (AOP_TYPE(result) == AOP_PCODE
11692 //      && AOP_TYPE(result) == AOP_IMMD
11693       && DCL_TYPE(ptype) == POINTER
11694       && !IS_BITFIELD(retype)
11695       && !IS_BITFIELD(resetype)) {
11696
11697         genDataPointerSet (right,result,ic);
11698         pic16_freeAsmop(result,NULL,ic,TRUE);
11699       return;
11700     }
11701
11702     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11703     pic16_aopOp(right,ic,FALSE);
11704     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11705
11706     /* if bitfield then unpack the bits */
11707     if (IS_BITFIELD(resetype)) {
11708       genPackBits (resetype, result, right, NULL, POINTER);
11709     } else {
11710       /* we have can just get the values */
11711       int size = AOP_SIZE(right);
11712       int offset = 0 ;    
11713
11714         pic16_loadFSR0(result, 0);
11715             
11716         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11717         while (size--) {
11718           if (AOP_TYPE(right) == AOP_LIT) {
11719             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11720             if (size) {
11721               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11722             } else {
11723               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11724             }
11725           } else { // no literal
11726             if(size) {
11727               pic16_emitpcode(POC_MOVFF,
11728                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11729                   pic16_popCopyReg(&pic16_pc_postinc0)));
11730             } else {
11731               pic16_emitpcode(POC_MOVFF,
11732                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11733                   pic16_popCopyReg(&pic16_pc_indf0)));
11734             }
11735           }
11736           
11737           offset++;
11738         }
11739     }
11740
11741     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11742     /* now some housekeeping stuff */
11743     if (aop) {
11744       /* we had to allocate for this iCode */
11745       pic16_freeAsmop(NULL,aop,ic,TRUE);
11746     } else { 
11747       /* we did not allocate which means left
11748        * already in a pointer register, then
11749        * if size > 0 && this could be used again
11750        * we have to point it back to where it 
11751        * belongs */
11752       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11753       if (AOP_SIZE(right) > 1
11754         && !OP_SYMBOL(result)->remat
11755         && ( OP_SYMBOL(result)->liveTo > ic->seq
11756         || ic->depth )) {
11757
11758           int size = AOP_SIZE(right) - 1;
11759
11760             while (size--)
11761               pic16_emitcode("decf","fsr0,f");
11762               //pic16_emitcode("dec","%s",rname);
11763       }
11764     }
11765
11766     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11767     /* done */
11768 //release:
11769     pic16_freeAsmop(right,NULL,ic,TRUE);
11770     pic16_freeAsmop(result,NULL,ic,TRUE);
11771 }
11772
11773 /*-----------------------------------------------------------------*/
11774 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11775 /*-----------------------------------------------------------------*/
11776 static void genPagedPointerSet (operand *right,
11777                                operand *result, 
11778                                iCode *ic)
11779 {
11780     asmop *aop = NULL;
11781     regs *preg = NULL ;
11782     char *rname , *l;
11783     sym_link *retype;
11784        
11785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11786
11787     retype= getSpec(operandType(right));
11788     
11789     pic16_aopOp(result,ic,FALSE);
11790     
11791     /* if the value is already in a pointer register
11792        then don't need anything more */
11793     if (!AOP_INPREG(AOP(result))) {
11794         /* otherwise get a free pointer register */
11795         aop = newAsmop(0);
11796         preg = getFreePtr(ic,&aop,FALSE);
11797         pic16_emitcode("mov","%s,%s",
11798                 preg->name,
11799                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11800         rname = preg->name ;
11801     } else
11802         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11803     
11804     pic16_freeAsmop(result,NULL,ic,TRUE);
11805     pic16_aopOp (right,ic,FALSE);
11806
11807     /* if bitfield then unpack the bits */
11808     if (IS_BITFIELD(retype)) 
11809         genPackBits (retype,result,right,rname,PPOINTER);
11810     else {
11811         /* we have can just get the values */
11812         int size = AOP_SIZE(right);
11813         int offset = 0 ;        
11814         
11815         while (size--) {
11816             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11817             
11818             MOVA(l);
11819             pic16_emitcode("movx","@%s,a",rname);
11820
11821             if (size)
11822                 pic16_emitcode("inc","%s",rname);
11823
11824             offset++;
11825         }
11826     }
11827     
11828     /* now some housekeeping stuff */
11829     if (aop) {
11830         /* we had to allocate for this iCode */
11831         pic16_freeAsmop(NULL,aop,ic,TRUE);
11832     } else { 
11833         /* we did not allocate which means left
11834            already in a pointer register, then
11835            if size > 0 && this could be used again
11836            we have to point it back to where it 
11837            belongs */
11838         if (AOP_SIZE(right) > 1 &&
11839             !OP_SYMBOL(result)->remat &&
11840             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11841               ic->depth )) {
11842             int size = AOP_SIZE(right) - 1;
11843             while (size--)
11844                 pic16_emitcode("dec","%s",rname);
11845         }
11846     }
11847
11848     /* done */
11849     pic16_freeAsmop(right,NULL,ic,TRUE);
11850     
11851         
11852 }
11853
11854 #if 0
11855 /* This code is not adjusted to PIC16 and fails utterly...
11856  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11857
11858 /*-----------------------------------------------------------------*/
11859 /* genFarPointerSet - set value from far space                     */
11860 /*-----------------------------------------------------------------*/
11861 static void genFarPointerSet (operand *right,
11862                               operand *result, iCode *ic)
11863 {
11864     int size, offset ;
11865     sym_link *retype = getSpec(operandType(right));
11866
11867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11868     pic16_aopOp(result,ic,FALSE);
11869
11870     /* if the operand is already in dptr 
11871     then we do nothing else we move the value to dptr */
11872     if (AOP_TYPE(result) != AOP_STR) {
11873         /* if this is remateriazable */
11874         if (AOP_TYPE(result) == AOP_IMMD)
11875             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11876         else { /* we need to get it byte by byte */
11877             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11878             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11879             if (options.model == MODEL_FLAT24)
11880             {
11881                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11882             }
11883         }
11884     }
11885     /* so dptr know contains the address */
11886     pic16_freeAsmop(result,NULL,ic,TRUE);
11887     pic16_aopOp(right,ic,FALSE);
11888
11889     /* if bit then unpack */
11890     if (IS_BITFIELD(retype)) 
11891         genPackBits(retype,result,right,"dptr",FPOINTER);
11892     else {
11893         size = AOP_SIZE(right);
11894         offset = 0 ;
11895
11896         while (size--) {
11897             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11898             MOVA(l);
11899             pic16_emitcode("movx","@dptr,a");
11900             if (size)
11901                 pic16_emitcode("inc","dptr");
11902         }
11903     }
11904
11905     pic16_freeAsmop(right,NULL,ic,TRUE);
11906 }
11907 #endif
11908
11909 /*-----------------------------------------------------------------*/
11910 /* genGenPointerSet - set value from generic pointer space         */
11911 /*-----------------------------------------------------------------*/
11912 #if 0
11913 static void genGenPointerSet (operand *right,
11914                               operand *result, iCode *ic)
11915 {
11916         int i, size, offset, lit;
11917         sym_link *retype = getSpec(operandType(right));
11918
11919         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11920
11921         pic16_aopOp(result,ic,FALSE);
11922         pic16_aopOp(right,ic,FALSE);
11923         size = AOP_SIZE(right);
11924         offset = 0;
11925
11926         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11927
11928         /* if the operand is already in dptr 
11929                 then we do nothing else we move the value to dptr */
11930         if (AOP_TYPE(result) != AOP_STR) {
11931                 /* if this is remateriazable */
11932                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11933                 // WARNING: anythig until "else" is untested!
11934                 if (AOP_TYPE(result) == AOP_IMMD) {
11935                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11936                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11937                         // load FSR0 from immediate
11938                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11939                         offset = 0;
11940                         while(size--) {
11941                                 if(size) {
11942                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11943                                 } else {
11944                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11945                                 }
11946                                 offset++;
11947                         }
11948                         goto release;
11949                 }
11950                 else { /* we need to get it byte by byte */
11951                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11952                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11953
11954                         // set up FSR0 with address of result
11955                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11956                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11957
11958                         /* hack hack! see if this the FSR. If so don't load W */
11959                         if(AOP_TYPE(right) != AOP_ACC) {
11960
11961                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11962
11963                                 if(AOP_TYPE(right) == AOP_LIT)
11964                                 {
11965                                         // copy literal
11966                                         // note: pic16_popGet handles sign extension
11967                                         for(i=0;i<size;i++) {
11968                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11969                                                 if(i < size-1)
11970                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11971                                                 else
11972                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11973                                         }
11974                                 } else {
11975                                         // copy regs
11976
11977                                         for(i=0;i<size;i++) {
11978                                                 if(i < size-1)
11979                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11980                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11981                                                 else
11982                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11983                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11984                                         }
11985                                 }
11986                                 goto release;
11987                         } 
11988                         // right = ACC
11989                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11990                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11991                         goto release;
11992         } // if (AOP_TYPE(result) != AOP_IMMD)
11993
11994         } // if (AOP_TYPE(result) != AOP_STR)
11995         /* so dptr know contains the address */
11996
11997
11998         /* if bit then unpack */
11999         if (IS_BITFIELD(retype)) 
12000                 genPackBits(retype,result,right,"dptr",GPOINTER);
12001         else {
12002                 size = AOP_SIZE(right);
12003                 offset = 0 ;
12004
12005                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12006
12007                 // set up FSR0 with address of result
12008                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12009                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12010         
12011                 while (size--) {
12012                         if (AOP_TYPE(right) == AOP_LIT) {
12013                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12014                                 if (size) {
12015                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12016                                 } else {
12017                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12018                                 }
12019                         } else { // no literal
12020                                 if(size) {
12021                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12022                                 } else {
12023                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12024                                 }
12025                         }
12026                         offset++;
12027                 }
12028         }
12029
12030         release:
12031         pic16_freeAsmop(right,NULL,ic,TRUE);
12032         pic16_freeAsmop(result,NULL,ic,TRUE);
12033 }
12034 #endif
12035
12036 static void genGenPointerSet (operand *right,
12037                               operand *result, iCode *ic)
12038 {
12039   int size;
12040   sym_link *retype = getSpec(operandType(result));
12041
12042     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12043
12044     pic16_aopOp(result,ic,FALSE);
12045     pic16_aopOp(right,ic,FALSE);
12046     size = AOP_SIZE(right);
12047
12048     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12049
12050
12051     /* if bit then unpack */
12052     if (IS_BITFIELD(retype)) {
12053 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12054       genPackBits(retype,result,right,"dptr",GPOINTER);
12055       goto release;
12056     }
12057
12058     size = AOP_SIZE(right);
12059
12060     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12061
12062
12063     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12064
12065     /* value of right+0 is placed on stack, which will be retrieved
12066      * by the support function thus restoring the stack. The important
12067      * thing is that there is no need to manually restore stack pointer
12068      * here */
12069     pushaop(AOP(right), 0);
12070 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12071     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12072     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12073     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12074     
12075     /* load address to write to in WREG:FSR0H:FSR0L */
12076     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12077                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12078     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12079                                 pic16_popCopyReg(&pic16_pc_prodl)));
12080     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12081     
12082     pic16_callGenericPointerRW(1, size);
12083
12084 release:
12085     pic16_freeAsmop(right,NULL,ic,TRUE);
12086     pic16_freeAsmop(result,NULL,ic,TRUE);
12087 }
12088
12089 /*-----------------------------------------------------------------*/
12090 /* genPointerSet - stores the value into a pointer location        */
12091 /*-----------------------------------------------------------------*/
12092 static void genPointerSet (iCode *ic)
12093 {    
12094   operand *right, *result ;
12095   sym_link *type, *etype;
12096   int p_type;
12097
12098     FENTRY;
12099
12100     right = IC_RIGHT(ic);
12101     result = IC_RESULT(ic) ;
12102
12103     /* depending on the type of pointer we need to
12104     move it to the correct pointer register */
12105     type = operandType(result);
12106     etype = getSpec(type);
12107     
12108     /* if left is of type of pointer then it is simple */
12109     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12110         p_type = DCL_TYPE(type);
12111     }
12112     else {
12113         /* we have to go by the storage class */
12114         p_type = PTR_TYPE(SPEC_OCLS(etype));
12115
12116 /*      if (SPEC_OCLS(etype)->codesp ) { */
12117 /*          p_type = CPOINTER ;  */
12118 /*      } */
12119 /*      else */
12120 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12121 /*              p_type = FPOINTER ; */
12122 /*          else */
12123 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12124 /*                  p_type = PPOINTER ; */
12125 /*              else */
12126 /*                  if (SPEC_OCLS(etype) == idata ) */
12127 /*                      p_type = IPOINTER ; */
12128 /*                  else */
12129 /*                      p_type = POINTER ; */
12130     }
12131
12132     /* now that we have the pointer type we assign
12133     the pointer values */
12134     switch (p_type) {
12135       case POINTER:
12136       case FPOINTER:
12137       case IPOINTER:
12138         genNearPointerSet (right,result,ic);
12139         break;
12140
12141       case PPOINTER:
12142         genPagedPointerSet (right,result,ic);
12143         break;
12144
12145 #if 0
12146       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12147       case FPOINTER:
12148         genFarPointerSet (right,result,ic);
12149         break;
12150 #endif
12151         
12152       case GPOINTER:
12153         genGenPointerSet (right,result,ic);
12154         break;
12155
12156       default:
12157         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12158           "genPointerSet: illegal pointer type");
12159     }
12160 }
12161
12162 /*-----------------------------------------------------------------*/
12163 /* genIfx - generate code for Ifx statement                        */
12164 /*-----------------------------------------------------------------*/
12165 static void genIfx (iCode *ic, iCode *popIc)
12166 {
12167   operand *cond = IC_COND(ic);
12168   int isbit =0;
12169
12170     FENTRY;
12171
12172     pic16_aopOp(cond,ic,FALSE);
12173
12174     /* get the value into acc */
12175     if (AOP_TYPE(cond) != AOP_CRY)
12176       pic16_toBoolean(cond);
12177     else
12178       isbit = 1;
12179     /* the result is now in the accumulator */
12180     pic16_freeAsmop(cond,NULL,ic,TRUE);
12181
12182     /* if there was something to be popped then do it */
12183     if (popIc)
12184       genIpop(popIc);
12185
12186     /* if the condition is  a bit variable */
12187     if (isbit && IS_ITEMP(cond) && 
12188         SPIL_LOC(cond)) {
12189       genIfxJump(ic,"c");
12190       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12191     } else {
12192       if (isbit && !IS_ITEMP(cond))
12193         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12194         else
12195         genIfxJump(ic,"a");
12196     }
12197     ic->generated = 1;
12198 }
12199
12200 /*-----------------------------------------------------------------*/
12201 /* genAddrOf - generates code for address of                       */
12202 /*-----------------------------------------------------------------*/
12203 static void genAddrOf (iCode *ic)
12204 {
12205   operand *result, *left;
12206   int size;
12207   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12208   pCodeOp *pcop0, *pcop1, *pcop2;
12209
12210     FENTRY;
12211
12212     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12213
12214     sym = OP_SYMBOL( IC_LEFT(ic) );
12215     
12216     if(sym->onStack) {
12217       /* get address of symbol on stack */
12218       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12219 #if 0
12220       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12221                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12222 #endif
12223
12224       // operands on stack are accessible via "FSR2 + index" with index
12225       // starting at 2 for arguments and growing from 0 downwards for
12226       // local variables (index == 0 is not assigned so we add one here)
12227       {
12228         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12229
12230           if (soffs <= 0) {
12231             assert (soffs < 0);
12232             soffs++;
12233           } // if
12234
12235           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12236           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12237           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12238           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12239           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12240           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12241           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12242       }
12243
12244       goto release;
12245     }
12246         
12247 //      if(pic16_debug_verbose) {
12248 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12249 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12250 //      }
12251         
12252     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12253     size = AOP_SIZE(IC_RESULT(ic));
12254
12255     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12256     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12257     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12258         
12259     if (size == 3) {
12260       pic16_emitpcode(POC_MOVLW, pcop0);
12261       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12262       pic16_emitpcode(POC_MOVLW, pcop1);
12263       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12264       pic16_emitpcode(POC_MOVLW, pcop2);
12265       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12266     } else
12267     if (size == 2) {
12268       pic16_emitpcode(POC_MOVLW, pcop0);
12269       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12270       pic16_emitpcode(POC_MOVLW, pcop1);
12271     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12272     } else {
12273       pic16_emitpcode(POC_MOVLW, pcop0);
12274       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12275     }
12276
12277     pic16_freeAsmop(left, NULL, ic, FALSE);
12278 release:
12279     pic16_freeAsmop(result,NULL,ic,TRUE);
12280 }
12281
12282
12283 #if 0
12284 /*-----------------------------------------------------------------*/
12285 /* genFarFarAssign - assignment when both are in far space         */
12286 /*-----------------------------------------------------------------*/
12287 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12288 {
12289     int size = AOP_SIZE(right);
12290     int offset = 0;
12291     char *l ;
12292     /* first push the right side on to the stack */
12293     while (size--) {
12294         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12295         MOVA(l);
12296         pic16_emitcode ("push","acc");
12297     }
12298     
12299     pic16_freeAsmop(right,NULL,ic,FALSE);
12300     /* now assign DPTR to result */
12301     pic16_aopOp(result,ic,FALSE);
12302     size = AOP_SIZE(result);
12303     while (size--) {
12304         pic16_emitcode ("pop","acc");
12305         pic16_aopPut(AOP(result),"a",--offset);
12306     }
12307     pic16_freeAsmop(result,NULL,ic,FALSE);
12308         
12309 }
12310 #endif
12311
12312 /*-----------------------------------------------------------------*/
12313 /* genAssign - generate code for assignment                        */
12314 /*-----------------------------------------------------------------*/
12315 static void genAssign (iCode *ic)
12316 {
12317   operand *result, *right;
12318   sym_link *restype, *rtype;
12319   int size, offset,know_W;
12320   unsigned long lit = 0L;
12321
12322     result = IC_RESULT(ic);
12323     right  = IC_RIGHT(ic) ;
12324
12325     FENTRY;
12326   
12327     /* if they are the same */
12328     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12329       return ;
12330
12331     /* reversed order operands are aopOp'ed so that result operand
12332      * is effective in case right is a stack symbol. This maneauver
12333      * allows to use the _G.resDirect flag later */
12334      pic16_aopOp(result,ic,TRUE);
12335     pic16_aopOp(right,ic,FALSE);
12336
12337     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12338
12339     /* if they are the same registers */
12340     if (pic16_sameRegs(AOP(right),AOP(result)))
12341       goto release;
12342
12343     /* if the result is a bit */
12344     if (AOP_TYPE(result) == AOP_CRY) {
12345       /* if the right size is a literal then
12346          we know what the value is */
12347       if (AOP_TYPE(right) == AOP_LIT) {
12348           
12349         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12350             pic16_popGet(AOP(result),0));
12351
12352         if (((int) operandLitValue(right))) 
12353           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12354               AOP(result)->aopu.aop_dir,
12355               AOP(result)->aopu.aop_dir);
12356         else
12357           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12358               AOP(result)->aopu.aop_dir,
12359               AOP(result)->aopu.aop_dir);
12360         
12361         goto release;
12362       }
12363
12364       /* the right is also a bit variable */
12365       if (AOP_TYPE(right) == AOP_CRY) {
12366         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12367         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12368         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12369
12370         goto release ;
12371       }
12372
12373       /* we need to or */
12374       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12375       pic16_toBoolean(right);
12376       emitSKPZ;
12377       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12378       //pic16_aopPut(AOP(result),"a",0);
12379       goto release ;
12380     }
12381
12382     /* bit variables done */
12383     /* general case */
12384     size = AOP_SIZE(result);
12385     offset = 0 ;
12386
12387   /* bit variables done */
12388   /* general case */
12389   size = AOP_SIZE(result);
12390   restype = operandType(result);
12391   rtype = operandType(right);
12392   offset = 0 ;
12393
12394   if(AOP_TYPE(right) == AOP_LIT) {
12395     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12396     {
12397       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12398
12399       /* patch tag for literals that are cast to pointers */
12400       if (IS_CODEPTR(restype)) {
12401         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12402         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12403       } else {
12404         if (IS_GENPTR(restype))
12405         {
12406           if (IS_CODEPTR(rtype)) {
12407             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12408             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12409           } else if (PIC_IS_DATA_PTR(rtype)) {
12410             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12411             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12412           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12413             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12414           } else if (IS_PTR(rtype)) {
12415             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12416             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12417           }
12418         }
12419       }
12420     } else {
12421       union {
12422         unsigned long lit_int;
12423         float lit_float;
12424       } info;
12425
12426
12427       if(IS_FIXED16X16(operandType(right))) {
12428         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12429       } else {
12430         /* take care if literal is a float */
12431         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12432         lit = info.lit_int;
12433       }
12434     }
12435   }
12436
12437 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12438 //                      sizeof(unsigned long int), sizeof(float));
12439
12440
12441     if (AOP_TYPE(right) == AOP_REG) {
12442       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12443       while (size--) {
12444         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12445       } // while
12446       goto release;
12447     }
12448
12449     /* when do we have to read the program memory?
12450      * - if right itself is a symbol in code space
12451      *   (we don't care what it points to if it's a pointer)
12452      * - AND right is not a function (we would want its address)
12453      */
12454     if(AOP_TYPE(right) != AOP_LIT
12455       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12456       && !IS_FUNC(OP_SYM_TYPE(right))
12457       && !IS_ITEMP(right)) {
12458
12459       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12460       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12461       
12462       // set up table pointer
12463       if(is_LitOp(right)) {
12464 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12465         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12466         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12467         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12468         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12469         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12470         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12471       } else {
12472 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12473         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12474             pic16_popCopyReg(&pic16_pc_tblptrl)));
12475         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12476             pic16_popCopyReg(&pic16_pc_tblptrh)));
12477         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12478             pic16_popCopyReg(&pic16_pc_tblptru)));
12479       }
12480
12481       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12482       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12483       while(size--) {
12484         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12485         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12486             pic16_popGet(AOP(result),offset)));
12487         offset++;
12488       }
12489
12490       /* FIXME: for pointers we need to extend differently (according
12491        * to pointer type DATA/CODE/EEPROM/... :*/
12492       size = getSize(OP_SYM_TYPE(right));
12493       if(AOP_SIZE(result) > size) {
12494         size = AOP_SIZE(result) - size;
12495         while(size--) {
12496           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12497           offset++;
12498         }
12499       }
12500       goto release;
12501     }
12502
12503 #if 0
12504     /* VR - What is this?! */
12505     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12506       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12507       
12508       if(aopIdx(AOP(result),0) == 4) {
12509         /* this is a workaround to save value of right into wreg too,
12510          * value of wreg is going to be used later */
12511         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12512         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12513         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12514         goto release;
12515       } else
12516 //      assert(0);
12517       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12518     }
12519 #endif
12520
12521   know_W=-1;
12522   while (size--) {
12523     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12524     if(AOP_TYPE(right) == AOP_LIT) {
12525       if(lit&0xff) {
12526         if(know_W != (lit&0xff))
12527           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12528         know_W = lit&0xff;
12529         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12530       } else
12531         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12532
12533       lit >>= 8;
12534
12535     } else if (AOP_TYPE(right) == AOP_CRY) {
12536       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12537       if(offset == 0) {
12538         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12539         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12540         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12541       }
12542     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12543         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12544         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12545     } else {
12546       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12547
12548       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12549           if(AOP_TYPE(result) == AOP_ACC) {
12550             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12551           } else
12552           if(AOP_TYPE(right) == AOP_ACC) {
12553             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12554           } else {
12555             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12556           }
12557       }
12558     }
12559       
12560       offset++;
12561     }
12562   
12563 release:
12564   pic16_freeAsmop (right,NULL,ic,FALSE);
12565   pic16_freeAsmop (result,NULL,ic,TRUE);
12566
12567
12568 /*-----------------------------------------------------------------*/
12569 /* genJumpTab - generates code for jump table                       */
12570 /*-----------------------------------------------------------------*/
12571 static void genJumpTab (iCode *ic)
12572 {
12573   symbol *jtab;
12574   char *l;
12575   pCodeOp *jt_offs;
12576   pCodeOp *jt_offs_hi;
12577   pCodeOp *jt_label;
12578
12579     FENTRY;
12580
12581     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12582     /* get the condition into accumulator */
12583     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12584     MOVA(l);
12585     /* multiply by three */
12586     pic16_emitcode("add","a,acc");
12587     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12588
12589     jtab = newiTempLabel(NULL);
12590     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12591     pic16_emitcode("jmp","@a+dptr");
12592     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12593
12594 #if 0
12595     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12596     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12597     emitSKPNC;
12598     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12599     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12600     pic16_emitpLabel(jtab->key);
12601
12602 #else
12603
12604     jt_offs = pic16_popGetTempReg(0);
12605     jt_offs_hi = pic16_popGetTempReg(1);
12606     jt_label = pic16_popGetLabel (jtab->key);
12607     //fprintf (stderr, "Creating jump table...\n");
12608
12609     // calculate offset into jump table (idx * sizeof (GOTO))
12610     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12611     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12612     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12613     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12614     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12615     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12616     pic16_emitpcode(POC_MOVWF , jt_offs);
12617
12618     // prepare PCLATx (set to first entry in jump table)
12619     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12620     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12621     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12622     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12623     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12624
12625     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12626     pic16_emitpcode(POC_ADDWF , jt_offs);
12627     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12628     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12629     emitSKPNC;
12630     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12631
12632     // release temporaries and prepare jump into table (new PCL --> WREG)
12633     pic16_emitpcode(POC_MOVFW , jt_offs);
12634     pic16_popReleaseTempReg (jt_offs_hi, 1);
12635     pic16_popReleaseTempReg (jt_offs, 0);
12636
12637     // jump into the table
12638     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12639
12640     pic16_emitpLabelFORCE(jtab->key);
12641 #endif
12642
12643     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12644 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12645
12646     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12647     /* now generate the jump labels */
12648     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12649          jtab = setNextItem(IC_JTLABELS(ic))) {
12650 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12651         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12652         
12653     }
12654     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12655
12656 }
12657
12658 /*-----------------------------------------------------------------*/
12659 /* genMixedOperation - gen code for operators between mixed types  */
12660 /*-----------------------------------------------------------------*/
12661 /*
12662   TSD - Written for the PIC port - but this unfortunately is buggy.
12663   This routine is good in that it is able to efficiently promote 
12664   types to different (larger) sizes. Unfortunately, the temporary
12665   variables that are optimized out by this routine are sometimes
12666   used in other places. So until I know how to really parse the 
12667   iCode tree, I'm going to not be using this routine :(.
12668 */
12669 static int genMixedOperation (iCode *ic)
12670 {
12671 #if 0
12672   operand *result = IC_RESULT(ic);
12673   sym_link *ctype = operandType(IC_LEFT(ic));
12674   operand *right = IC_RIGHT(ic);
12675   int ret = 0;
12676   int big,small;
12677   int offset;
12678
12679   iCode *nextic;
12680   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12681
12682   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12683
12684   nextic = ic->next;
12685   if(!nextic)
12686     return 0;
12687
12688   nextright = IC_RIGHT(nextic);
12689   nextleft  = IC_LEFT(nextic);
12690   nextresult = IC_RESULT(nextic);
12691
12692   pic16_aopOp(right,ic,FALSE);
12693   pic16_aopOp(result,ic,FALSE);
12694   pic16_aopOp(nextright,  nextic, FALSE);
12695   pic16_aopOp(nextleft,   nextic, FALSE);
12696   pic16_aopOp(nextresult, nextic, FALSE);
12697
12698   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12699
12700     operand *t = right;
12701     right = nextright;
12702     nextright = t; 
12703
12704     pic16_emitcode(";remove right +","");
12705
12706   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12707 /*
12708     operand *t = right;
12709     right = nextleft;
12710     nextleft = t; 
12711 */
12712     pic16_emitcode(";remove left +","");
12713   } else
12714     return 0;
12715
12716   big = AOP_SIZE(nextleft);
12717   small = AOP_SIZE(nextright);
12718
12719   switch(nextic->op) {
12720
12721   case '+':
12722     pic16_emitcode(";optimize a +","");
12723     /* if unsigned or not an integral type */
12724     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12725       pic16_emitcode(";add a bit to something","");
12726     } else {
12727
12728       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12729
12730       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12731         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12732         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12733       } else
12734         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12735
12736       offset = 0;
12737       while(--big) {
12738
12739         offset++;
12740
12741         if(--small) {
12742           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12743             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12744             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12745           }
12746
12747           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12748           emitSKPNC;
12749           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12750                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12751                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12752           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12753           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12754
12755         } else {
12756           pic16_emitcode("rlf","known_zero,w");
12757
12758           /*
12759             if right is signed
12760               btfsc  right,7
12761                addlw ff
12762           */
12763           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12764             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12766           } else {
12767             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12768           }
12769         }
12770       }
12771       ret = 1;
12772     }
12773   }
12774   ret = 1;
12775
12776 release:
12777   pic16_freeAsmop(right,NULL,ic,TRUE);
12778   pic16_freeAsmop(result,NULL,ic,TRUE);
12779   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12780   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12781   if(ret)
12782     nextic->generated = 1;
12783
12784   return ret;
12785 #else
12786   return 0;
12787 #endif
12788 }
12789 /*-----------------------------------------------------------------*/
12790 /* genCast - gen code for casting                                  */
12791 /*-----------------------------------------------------------------*/
12792 static void genCast (iCode *ic)
12793 {
12794   operand *result = IC_RESULT(ic);
12795   sym_link *ctype = operandType(IC_LEFT(ic));
12796   sym_link *rtype = operandType(IC_RIGHT(ic));
12797   sym_link *restype = operandType(IC_RESULT(ic));
12798   operand *right = IC_RIGHT(ic);
12799   int size, offset ;
12800
12801
12802     FENTRY;
12803
12804         /* if they are equivalent then do nothing */
12805 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12806 //              return ;
12807
12808         pic16_aopOp(result,ic,FALSE);
12809         pic16_aopOp(right,ic,FALSE) ;
12810
12811         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12812
12813
12814         /* if the result is a bit */
12815         if (AOP_TYPE(result) == AOP_CRY) {
12816         
12817                 /* if the right size is a literal then
12818                  * we know what the value is */
12819                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12820
12821                 if (AOP_TYPE(right) == AOP_LIT) {
12822                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12823                                 pic16_popGet(AOP(result),0));
12824
12825                         if (((int) operandLitValue(right))) 
12826                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12827                                         AOP(result)->aopu.aop_dir,
12828                                         AOP(result)->aopu.aop_dir);
12829                         else
12830                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12831                                         AOP(result)->aopu.aop_dir,
12832                                         AOP(result)->aopu.aop_dir);
12833                         goto release;
12834                 }
12835
12836                 /* the right is also a bit variable */
12837                 if (AOP_TYPE(right) == AOP_CRY) {
12838                         emitCLRC;
12839                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12840
12841                         pic16_emitcode("clrc","");
12842                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12843                                 AOP(right)->aopu.aop_dir,
12844                                 AOP(right)->aopu.aop_dir);
12845                         pic16_aopPut(AOP(result),"c",0);
12846                         goto release ;
12847                 }
12848
12849                 /* we need to or */
12850                 if (AOP_TYPE(right) == AOP_REG) {
12851                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12852                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12853                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12854                 }
12855                 pic16_toBoolean(right);
12856                 pic16_aopPut(AOP(result),"a",0);
12857                 goto release ;
12858         }
12859
12860         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12861           int offset = 1;
12862
12863                 size = AOP_SIZE(result);
12864
12865                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12866
12867                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12868                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12869                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12870
12871                 while (size--)
12872                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12873
12874                 goto release;
12875         }
12876
12877         if(IS_BITFIELD(getSpec(restype))
12878           && IS_BITFIELD(getSpec(rtype))) {
12879           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12880         }
12881         
12882         /* port from pic14 to cope with generic pointers */
12883         if (PIC_IS_TAGGED(restype))
12884         {
12885           operand *result = IC_RESULT(ic);
12886           //operand *left = IC_LEFT(ic);
12887           operand *right = IC_RIGHT(ic);
12888           int tag = 0xff;
12889
12890           /* copy common part */
12891           int max, size = AOP_SIZE(result);
12892           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12893           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12894
12895           max = size;
12896           while (size--)
12897           {
12898             pic16_mov2w (AOP(right), size);
12899             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12900           } // while
12901
12902           /* upcast into generic pointer type? */
12903           if (IS_GENPTR(restype)
12904               && !PIC_IS_TAGGED(rtype)
12905               && (AOP_SIZE(result) > max))
12906           {
12907             /* determine appropriate tag for right */
12908             if (PIC_IS_DATA_PTR(rtype))
12909               tag = GPTR_TAG_DATA;
12910             else if (IS_CODEPTR(rtype))
12911               tag = GPTR_TAG_CODE;
12912             else if (PIC_IS_DATA_PTR(ctype)) {
12913               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12914               tag = GPTR_TAG_DATA;
12915             } else if (IS_CODEPTR(ctype)) {
12916               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12917               tag = GPTR_TAG_CODE;
12918             } else if (IS_PTR(rtype)) {
12919               PERFORM_ONCE(weirdcast,
12920               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12921               );
12922               tag = GPTR_TAG_DATA;
12923             } else {
12924               PERFORM_ONCE(weirdcast,
12925               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12926               );
12927               tag = GPTR_TAG_DATA;
12928             }
12929
12930             assert (AOP_SIZE(result) == 3);
12931             /* zero-extend address... */
12932             for (size = max; size < AOP_SIZE(result)-1; size++)
12933               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12934             /* ...and add tag */
12935             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12936           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12937             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12938             for (size = max; size < AOP_SIZE(result)-1; size++)
12939               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12940             /* add __code tag */
12941             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12942           } else if (AOP_SIZE(result) > max) {
12943             /* extend non-pointers */
12944             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12945             pic16_addSign(result, max, 0);
12946           } // if
12947           goto release;
12948         }
12949
12950         /* if they are the same size : or less */
12951         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12952
12953                 /* if they are in the same place */
12954                 if (pic16_sameRegs(AOP(right),AOP(result)))
12955                         goto release;
12956
12957                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12958 #if 0
12959                 if (IS_PTR_CONST(rtype))
12960 #else
12961                 if (IS_CODEPTR(rtype))
12962 #endif
12963                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12964
12965 #if 0
12966                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12967 #else
12968                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12969 #endif
12970                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12971
12972 #if 0
12973                 if(AOP_TYPE(right) == AOP_IMMD) {
12974                   pCodeOp *pcop0, *pcop1, *pcop2;
12975                   symbol *sym = OP_SYMBOL( right );
12976
12977                         size = AOP_SIZE(result);
12978                         /* low */
12979                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12980                         /* high */
12981                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12982                         /* upper */
12983                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12984         
12985                         if (size == 3) {
12986                                 pic16_emitpcode(POC_MOVLW, pcop0);
12987                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12988                                 pic16_emitpcode(POC_MOVLW, pcop1);
12989                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12990                                 pic16_emitpcode(POC_MOVLW, pcop2);
12991                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12992                         } else
12993                         if (size == 2) {
12994                                 pic16_emitpcode(POC_MOVLW, pcop0);
12995                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12996                                 pic16_emitpcode(POC_MOVLW, pcop1);
12997                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12998                         } else {
12999                                 pic16_emitpcode(POC_MOVLW, pcop0);
13000                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13001                         }
13002                 } else
13003 #endif
13004                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13005                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13006                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13007                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13008                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13009                         if(AOP_SIZE(result) <2)
13010                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13011                 } else {
13012                         /* if they in different places then copy */
13013                         size = AOP_SIZE(result);
13014                         offset = 0 ;
13015                         while (size--) {
13016                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13017                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13018                                 offset++;
13019                         }
13020                 }
13021                 goto release;
13022         }
13023
13024         /* if the result is of type pointer */
13025         if (IS_PTR(ctype)) {
13026           int p_type;
13027           sym_link *type = operandType(right);
13028           sym_link *etype = getSpec(type);
13029
13030                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13031
13032                 /* pointer to generic pointer */
13033                 if (IS_GENPTR(ctype)) {
13034                   char *l = zero;
13035             
13036                         if (IS_PTR(type)) 
13037                                 p_type = DCL_TYPE(type);
13038                         else {
13039                 /* we have to go by the storage class */
13040                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13041
13042 /*              if (SPEC_OCLS(etype)->codesp )  */
13043 /*                  p_type = CPOINTER ;  */
13044 /*              else */
13045 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13046 /*                      p_type = FPOINTER ; */
13047 /*                  else */
13048 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13049 /*                          p_type = PPOINTER; */
13050 /*                      else */
13051 /*                          if (SPEC_OCLS(etype) == idata ) */
13052 /*                              p_type = IPOINTER ; */
13053 /*                          else */
13054 /*                              p_type = POINTER ; */
13055             }
13056                 
13057             /* the first two bytes are known */
13058       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13059             size = GPTRSIZE - 1; 
13060             offset = 0 ;
13061             while (size--) {
13062               if(offset < AOP_SIZE(right)) {
13063                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13064                 pic16_mov2f(AOP(result), AOP(right), offset);
13065 /*
13066                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13067                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13068                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13069                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13070                 } else { 
13071                   
13072                   pic16_aopPut(AOP(result),
13073                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13074                          offset);
13075                 }
13076 */
13077               } else 
13078                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13079               offset++;
13080             }
13081             /* the last byte depending on type */
13082             switch (p_type) {
13083             case IPOINTER:
13084             case POINTER:
13085             case FPOINTER:
13086                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13087                 break;
13088
13089             case CPOINTER:
13090                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13091                 break;
13092
13093             case PPOINTER:
13094               pic16_emitcode(";BUG!? ","%d",__LINE__);
13095                 l = "#0x03";
13096                 break;
13097
13098             case GPOINTER:
13099                 if (GPTRSIZE > AOP_SIZE(right)) {
13100                   // assume __data pointer... THIS MIGHT BE WRONG!
13101                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13102                 } else {
13103                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13104                 }
13105               break;
13106               
13107             default:
13108                 /* this should never happen */
13109                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13110                        "got unknown pointer type");
13111                 exit(1);
13112             }
13113             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13114             goto release ;
13115         }
13116         
13117         
13118         assert( 0 );
13119         /* just copy the pointers */
13120         size = AOP_SIZE(result);
13121         offset = 0 ;
13122         while (size--) {
13123             pic16_aopPut(AOP(result),
13124                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13125                    offset);
13126             offset++;
13127         }
13128         goto release ;
13129     }
13130     
13131
13132
13133     /* so we now know that the size of destination is greater
13134     than the size of the source.
13135     Now, if the next iCode is an operator then we might be
13136     able to optimize the operation without performing a cast.
13137     */
13138     if(genMixedOperation(ic))
13139       goto release;
13140
13141     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13142     
13143     /* we move to result for the size of source */
13144     size = AOP_SIZE(right);
13145     offset = 0 ;
13146
13147     while (size--) {
13148       if(!_G.resDirect)
13149         pic16_mov2f(AOP(result), AOP(right), offset);
13150       offset++;
13151     }
13152
13153     /* now depending on the sign of the destination */
13154     size = AOP_SIZE(result) - AOP_SIZE(right);
13155     /* if unsigned or not an integral type */
13156     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13157       while (size--)
13158         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13159     } else {
13160       /* we need to extend the sign :( */
13161
13162       if(size == 1) {
13163         /* Save one instruction of casting char to int */
13164         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13165         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13166         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13167       } else {
13168         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13169
13170         if(offset)
13171           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13172         else
13173           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13174         
13175         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13176
13177         while (size--)
13178           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13179       }
13180     }
13181
13182 release:
13183     pic16_freeAsmop(right,NULL,ic,TRUE);
13184     pic16_freeAsmop(result,NULL,ic,TRUE);
13185
13186 }
13187
13188 /*-----------------------------------------------------------------*/
13189 /* genDjnz - generate decrement & jump if not zero instrucion      */
13190 /*-----------------------------------------------------------------*/
13191 static int genDjnz (iCode *ic, iCode *ifx)
13192 {
13193     symbol *lbl, *lbl1;
13194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13195
13196     if (!ifx)
13197         return 0;
13198     
13199     /* if the if condition has a false label
13200        then we cannot save */
13201     if (IC_FALSE(ifx))
13202         return 0;
13203
13204     /* if the minus is not of the form 
13205        a = a - 1 */
13206     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13207         !IS_OP_LITERAL(IC_RIGHT(ic)))
13208         return 0;
13209
13210     if (operandLitValue(IC_RIGHT(ic)) != 1)
13211         return 0;
13212
13213     /* if the size of this greater than one then no
13214        saving */
13215     if (getSize(operandType(IC_RESULT(ic))) > 1)
13216         return 0;
13217
13218     /* otherwise we can save BIG */
13219     lbl = newiTempLabel(NULL);
13220     lbl1= newiTempLabel(NULL);
13221
13222     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13223     
13224     if (IS_AOP_PREG(IC_RESULT(ic))) {
13225         pic16_emitcode("dec","%s",
13226                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13227         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13228         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13229     } else {    
13230
13231
13232       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13233       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13234
13235       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13236       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13237
13238     }
13239     
13240     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13241     ifx->generated = 1;
13242     return 1;
13243 }
13244
13245 /*-----------------------------------------------------------------*/
13246 /* genReceive - generate code for a receive iCode                  */
13247 /*-----------------------------------------------------------------*/
13248 static void genReceive (iCode *ic)
13249 {    
13250
13251   FENTRY;
13252
13253 #if 0
13254   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13255         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13256 #endif
13257 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13258
13259   if (isOperandInFarSpace(IC_RESULT(ic))
13260       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13261           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13262
13263     int size = getSize(operandType(IC_RESULT(ic)));
13264     int offset =  pic16_fReturnSizePic - size;
13265
13266       assert( 0 );
13267       while (size--) {
13268         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13269                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13270                       offset++;
13271         }
13272
13273       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13274
13275       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13276       size = AOP_SIZE(IC_RESULT(ic));
13277       offset = 0;
13278       while (size--) {
13279         pic16_emitcode ("pop","acc");
13280         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13281       }
13282   } else {
13283     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13284     _G.accInUse++;
13285     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13286     _G.accInUse--;
13287
13288     /* set pseudo stack pointer to where it should be - dw*/
13289     GpsuedoStkPtr = ic->parmBytes;
13290
13291     /* setting GpsuedoStkPtr has side effects here: */
13292     assignResultValue(IC_RESULT(ic), 0);
13293   }
13294
13295   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13296 }
13297
13298 /*-----------------------------------------------------------------*/
13299 /* genDummyRead - generate code for dummy read of volatiles        */
13300 /*-----------------------------------------------------------------*/
13301 static void
13302 genDummyRead (iCode * ic)
13303 {
13304   operand *op;
13305   int i;
13306
13307   op = IC_RIGHT(ic);
13308   if (op && IS_SYMOP(op)) {
13309     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13310       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13311       return;
13312     }
13313     pic16_aopOp (op, ic, FALSE);
13314     for (i=0; i < AOP_SIZE(op); i++) {
13315       // may need to protect this from the peepholer -- this is not nice but works...
13316       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13317       pic16_mov2w (AOP(op),i);
13318       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13319     } // for i
13320     pic16_freeAsmop (op, NULL, ic, TRUE);
13321   } else if (op) {
13322     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13323   } // if
13324 }
13325
13326 /*-----------------------------------------------------------------*/
13327 /* genpic16Code - generate code for pic16 based controllers        */
13328 /*-----------------------------------------------------------------*/
13329 /*
13330  * At this point, ralloc.c has gone through the iCode and attempted
13331  * to optimize in a way suitable for a PIC. Now we've got to generate
13332  * PIC instructions that correspond to the iCode.
13333  *
13334  * Once the instructions are generated, we'll pass through both the
13335  * peep hole optimizer and the pCode optimizer.
13336  *-----------------------------------------------------------------*/
13337
13338 void genpic16Code (iCode *lic)
13339 {
13340   iCode *ic;
13341   int cln = 0;
13342
13343     lineHead = lineCurr = NULL;
13344
13345     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13346     pic16_addpBlock(pb);
13347
13348 #if 0
13349     /* if debug information required */
13350     if (options.debug && currFunc) {
13351       if (currFunc) {
13352         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13353       }
13354     }
13355 #endif
13356
13357     for (ic = lic ; ic ; ic = ic->next ) {
13358
13359       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13360       if ( cln != ic->lineno ) {
13361         if ( options.debug ) {
13362           debugFile->writeCLine (ic);
13363         }
13364         
13365         if(!options.noCcodeInAsm) {
13366           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13367               printCLine(ic->filename, ic->lineno)));
13368         }
13369
13370         cln = ic->lineno ;
13371       }
13372         
13373       if(options.iCodeInAsm) {
13374         char *l;
13375
13376           /* insert here code to print iCode as comment */
13377           l = Safe_strdup(printILine(ic));
13378           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13379       }
13380
13381       /* if the result is marked as
13382        * spilt and rematerializable or code for
13383        * this has already been generated then
13384        * do nothing */
13385       if (resultRemat(ic) || ic->generated ) 
13386         continue ;
13387         
13388       /* depending on the operation */
13389       switch (ic->op) {
13390         case '!' :
13391           pic16_genNot(ic);
13392           break;
13393             
13394         case '~' :
13395           pic16_genCpl(ic);
13396           break;
13397             
13398         case UNARYMINUS:
13399           genUminus (ic);
13400           break;
13401             
13402         case IPUSH:
13403           genIpush (ic);
13404           break;
13405             
13406         case IPOP:
13407           /* IPOP happens only when trying to restore a 
13408            * spilt live range, if there is an ifx statement
13409            * following this pop then the if statement might
13410            * be using some of the registers being popped which
13411            * would destroy the contents of the register so
13412            * we need to check for this condition and handle it */
13413            if (ic->next
13414              && ic->next->op == IFX
13415              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13416                genIfx (ic->next,ic);
13417           else
13418             genIpop (ic);
13419           break; 
13420             
13421         case CALL:
13422           genCall (ic);
13423           break;
13424             
13425         case PCALL:
13426           genPcall (ic);
13427           break;
13428             
13429         case FUNCTION:
13430           genFunction (ic);
13431           break;
13432             
13433         case ENDFUNCTION:
13434           genEndFunction (ic);
13435           break;
13436             
13437         case RETURN:
13438           genRet (ic);
13439           break;
13440             
13441         case LABEL:
13442           genLabel (ic);
13443           break;
13444             
13445         case GOTO:
13446           genGoto (ic);
13447           break;
13448             
13449         case '+' :
13450           pic16_genPlus (ic) ;
13451           break;
13452             
13453         case '-' :
13454           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13455             pic16_genMinus (ic);
13456           break;
13457
13458         case '*' :
13459           genMult (ic);
13460           break;
13461             
13462         case '/' :
13463           genDiv (ic) ;
13464           break;
13465             
13466         case '%' :
13467           genMod (ic);
13468           break;
13469             
13470         case '>' :
13471           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13472           break;
13473             
13474         case '<' :
13475           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13476           break;
13477             
13478         case LE_OP:
13479         case GE_OP:
13480         case NE_OP:
13481           /* note these two are xlated by algebraic equivalence
13482            * during parsing SDCC.y */
13483           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13484             "got '>=' or '<=' shouldn't have come here");
13485           break;
13486
13487         case EQ_OP:
13488           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13489           break;            
13490             
13491         case AND_OP:
13492           genAndOp (ic);
13493           break;
13494             
13495         case OR_OP:
13496           genOrOp (ic);
13497           break;
13498             
13499         case '^' :
13500           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13501           break;
13502             
13503         case '|' :
13504           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13505           break;
13506             
13507         case BITWISEAND:
13508           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13509           break;
13510             
13511         case INLINEASM:
13512           genInline (ic);
13513           break;
13514             
13515         case RRC:
13516           genRRC (ic);
13517           break;
13518             
13519         case RLC:
13520           genRLC (ic);
13521           break;
13522             
13523         case GETHBIT:
13524           genGetHbit (ic);
13525           break;
13526             
13527         case LEFT_OP:
13528           genLeftShift (ic);
13529           break;
13530             
13531         case RIGHT_OP:
13532           genRightShift (ic);
13533           break;
13534             
13535         case GET_VALUE_AT_ADDRESS:
13536           genPointerGet(ic);
13537           break;
13538             
13539         case '=' :
13540           if (POINTER_SET(ic))
13541             genPointerSet(ic);
13542           else
13543             genAssign(ic);
13544           break;
13545             
13546         case IFX:
13547           genIfx (ic,NULL);
13548           break;
13549             
13550         case ADDRESS_OF:
13551           genAddrOf (ic);
13552           break;
13553             
13554         case JUMPTABLE:
13555           genJumpTab (ic);
13556           break;
13557             
13558         case CAST:
13559           genCast (ic);
13560           break;
13561             
13562         case RECEIVE:
13563           genReceive(ic);
13564           break;
13565             
13566         case SEND:
13567           addSet(&_G.sendSet,ic);
13568           break;
13569
13570         case DUMMY_READ_VOLATILE:
13571           genDummyRead (ic);
13572           break;
13573
13574         default :
13575           ic = ic;
13576       }
13577     }
13578
13579
13580     /* now we are ready to call the
13581        peep hole optimizer */
13582     if (!options.nopeep)
13583       peepHole (&lineHead);
13584
13585     /* now do the actual printing */
13586     printLine (lineHead, codeOutFile);
13587
13588 #ifdef PCODE_DEBUG
13589     DFPRINTF((stderr,"printing pBlock\n\n"));
13590     pic16_printpBlock(stdout,pb);
13591 #endif
13592
13593     return;
13594 }
13595