* src/pic16/gen.c (genPcall): fixed bug #1443644
[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 = 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 = 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:%d: getting free ptr from ic = %c result: %d\n", __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         sym->aop = aop = newAsmop (AOP_DIR);
855         aop->aopu.aop_dir = sym->rname ;
856         aop->size = getSize(sym->type);
857         DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
858         pic16_allocDirReg( IC_LEFT(ic) );
859         return aop;
860     }
861
862
863     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
864         sym->aop = aop = newAsmop (AOP_DIR);
865         aop->aopu.aop_dir = sym->rname ;
866         aop->size = getSize(sym->type);
867         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
868         pic16_allocDirReg( IC_LEFT(ic) );
869         return aop;
870     }
871
872
873     /* only remaining is far space */
874     sym->aop = aop = newAsmop(AOP_PCODE);
875
876 /* change the next if to 1 to revert to good old immediate code */
877         if(IN_CODESPACE(space)) {
878                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
879                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
880                 PCOI(aop->aopu.pcop)->index = 0;
881         } else {
882                 /* try to allocate via direct register */
883                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
884 //              aop->size = getSize( sym->type );
885         }
886
887         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
888                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
889
890 #if 0
891         if(!pic16_allocDirReg (IC_LEFT(ic)))
892                 return NULL;
893 #endif
894
895         if(IN_DIRSPACE( space ))
896                 aop->size = PTRSIZE;
897         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
898                 aop->size = FPTRSIZE;
899         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
900         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
901         else if(sym->onStack) {
902                 aop->size = PTRSIZE;
903         } else {
904           if(SPEC_SCLS(sym->etype) == S_PDATA) {
905             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
906             aop->size = FPTRSIZE;
907           } else
908                 assert( 0 );
909         }
910
911     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
912
913     /* if it is in code space */
914     if (IN_CODESPACE(space))
915         aop->code = 1;
916
917     return aop;     
918 }
919
920 /*-----------------------------------------------------------------*/
921 /* aopForRemat - rematerialzes an object                           */
922 /*-----------------------------------------------------------------*/
923 static asmop *aopForRemat (operand *op) // x symbol *sym)
924 {
925   symbol *sym = OP_SYMBOL(op);
926   operand *refop;
927   iCode *ic = NULL, *oldic;
928   asmop *aop = newAsmop(AOP_PCODE);
929   int val = 0;
930   int offset = 0;
931   int viaimmd=0;
932
933     FENTRY2;
934     
935         ic = sym->rematiCode;
936
937         if(IS_OP_POINTER(op)) {
938                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
939         }
940
941         for (;;) {
942                 oldic = ic;
943
944 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
945         
946                 if (ic->op == '+') {
947                         val += (int) operandLitValue(IC_RIGHT(ic));
948                 } else if (ic->op == '-') {
949                         val -= (int) operandLitValue(IC_RIGHT(ic));
950                 } else
951                         break;
952                 
953                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
954         }
955
956         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
957         refop = IC_LEFT(ic);
958
959         if(!op->isaddr)viaimmd++; else viaimmd=0;
960                 
961 /* set the following if to 1 to revert to good old immediate code */
962         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
963                 || viaimmd) {
964
965                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
966
967                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
968
969 #if 0
970                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
971 #else
972                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
973 #endif
974
975                 PCOI(aop->aopu.pcop)->index = val;
976                 
977                 aop->size = getSize( sym->type );
978         } else {
979                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
980
981                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
982                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
983
984                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
985         }
986
987
988         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
989                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
990 #if 0
991                 val, IS_PTR_CONST(operandType(op)));
992 #else
993                 val, IS_CODEPTR(operandType(op)));
994 #endif
995
996 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
997
998         pic16_allocDirReg (IC_LEFT(ic));
999
1000         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1001                 aop->code = 1;
1002
1003   return aop;        
1004 }
1005
1006 #if 0
1007 static int aopIdx (asmop *aop, int offset)
1008 {
1009   if(!aop)
1010     return -1;
1011
1012   if(aop->type !=  AOP_REG)
1013     return -2;
1014         
1015   return aop->aopu.aop_reg[offset]->rIdx;
1016
1017 }
1018 #endif
1019
1020 /*-----------------------------------------------------------------*/
1021 /* regsInCommon - two operands have some registers in common       */
1022 /*-----------------------------------------------------------------*/
1023 static bool regsInCommon (operand *op1, operand *op2)
1024 {
1025     symbol *sym1, *sym2;
1026     int i;
1027
1028     /* if they have registers in common */
1029     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1030         return FALSE ;
1031
1032     sym1 = OP_SYMBOL(op1);
1033     sym2 = OP_SYMBOL(op2);
1034
1035     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1036         return FALSE ;
1037
1038     for (i = 0 ; i < sym1->nRegs ; i++) {
1039         int j;
1040         if (!sym1->regs[i])
1041             continue ;
1042
1043         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1044             if (!sym2->regs[j])
1045                 continue ;
1046
1047             if (sym2->regs[j] == sym1->regs[i])
1048                 return TRUE ;
1049         }
1050     }
1051
1052     return FALSE ;
1053 }
1054
1055 /*-----------------------------------------------------------------*/
1056 /* operandsEqu - equivalent                                        */
1057 /*-----------------------------------------------------------------*/
1058 static bool operandsEqu ( operand *op1, operand *op2)
1059 {
1060     symbol *sym1, *sym2;
1061
1062     /* if they not symbols */
1063     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1064         return FALSE;
1065
1066     sym1 = OP_SYMBOL(op1);
1067     sym2 = OP_SYMBOL(op2);
1068
1069     /* if both are itemps & one is spilt
1070        and the other is not then false */
1071     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1072         sym1->isspilt != sym2->isspilt )
1073         return FALSE ;
1074
1075     /* if they are the same */
1076     if (sym1 == sym2)
1077         return TRUE ;
1078
1079     if (sym1->rname[0] && sym2->rname[0]
1080         && strcmp (sym1->rname, sym2->rname) == 0)
1081         return TRUE;
1082
1083
1084     /* if left is a tmp & right is not */
1085     if (IS_ITEMP(op1)  && 
1086         !IS_ITEMP(op2) &&
1087         sym1->isspilt  &&
1088         (sym1->usl.spillLoc == sym2))
1089         return TRUE;
1090
1091     if (IS_ITEMP(op2)  && 
1092         !IS_ITEMP(op1) &&
1093         sym2->isspilt  &&
1094         sym1->level > 0 &&
1095         (sym2->usl.spillLoc == sym1))
1096         return TRUE ;
1097
1098     return FALSE ;
1099 }
1100
1101 /*-----------------------------------------------------------------*/
1102 /* pic16_sameRegs - two asmops have the same registers                   */
1103 /*-----------------------------------------------------------------*/
1104 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1105 {
1106     int i;
1107
1108     if (aop1 == aop2)
1109         return TRUE ;
1110
1111     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1112                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1113
1114     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1115
1116     if (aop1->type != AOP_REG ||
1117         aop2->type != AOP_REG )
1118         return FALSE ;
1119
1120     /* This is a bit too restrictive if one is a subset of the other...
1121     if (aop1->size != aop2->size )
1122         return FALSE ;
1123     */
1124
1125     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1126 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1127
1128 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1129         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1130             return FALSE ;
1131     }
1132
1133     return TRUE ;
1134 }
1135
1136 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1137 {
1138     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1139                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1140
1141     if(aop1 == aop2)return TRUE;
1142     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1143       
1144       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1145     
1146   return TRUE;
1147 }
1148
1149
1150 /*-----------------------------------------------------------------*/
1151 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1152 /*-----------------------------------------------------------------*/
1153 void pic16_aopOp (operand *op, iCode *ic, bool result)
1154 {
1155     asmop *aop;
1156     symbol *sym;
1157     int i;
1158
1159     if (!op)
1160         return ;
1161
1162     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1163
1164     /* if this a literal */
1165     if (IS_OP_LITERAL(op)) {
1166         op->aop = aop = newAsmop(AOP_LIT);
1167         aop->aopu.aop_lit = op->operand.valOperand;
1168         aop->size = getSize(operandType(op));
1169         return;
1170     }
1171
1172     {
1173       sym_link *type = operandType(op);
1174 #if 0
1175       if(IS_PTR_CONST(type))
1176 #else
1177       if(IS_CODEPTR(type))
1178 #endif
1179         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1180     }
1181
1182     /* if already has a asmop then continue */
1183     if (op->aop)
1184         return ;
1185
1186     /* if the underlying symbol has a aop */
1187     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1188       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1189         op->aop = OP_SYMBOL(op)->aop;
1190         return;
1191     }
1192
1193     /* if this is a true symbol */
1194     if (IS_TRUE_SYMOP(op)) {    
1195         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1196       op->aop = aopForSym(ic, op, result);
1197       return ;
1198     }
1199
1200     /* this is a temporary : this has
1201     only four choices :
1202     a) register
1203     b) spillocation
1204     c) rematerialize 
1205     d) conditional   
1206     e) can be a return use only */
1207
1208     sym = OP_SYMBOL(op);
1209
1210     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1211     /* if the type is a conditional */
1212     if (sym->regType == REG_CND) {
1213         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1214         aop->size = 0;
1215         return;
1216     }
1217
1218     /* if it is spilt then two situations
1219     a) is rematerialize 
1220     b) has a spill location */
1221     if (sym->isspilt || sym->nRegs == 0) {
1222
1223 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1224       DEBUGpic16_emitcode(";","%d",__LINE__);
1225         /* rematerialize it NOW */
1226         if (sym->remat) {
1227
1228             sym->aop = op->aop = aop = aopForRemat (op);
1229 //            aop->size = getSize(sym->type);
1230 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1231             return;
1232         }
1233
1234 #if 1
1235         if (sym->accuse) {
1236             int i;
1237             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1238             aop->size = getSize(sym->type);
1239             for ( i = 0 ; i < 1 ; i++ ) {
1240                 aop->aopu.aop_str[i] = accUse[i];
1241 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1242             }
1243             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1244             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1245             return;  
1246         }
1247 #endif
1248
1249 #if 1
1250         if (sym->ruonly) {
1251           /*
1252           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1253           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1254           //pic16_allocDirReg (IC_LEFT(ic));
1255           aop->size = getSize(sym->type);
1256           */
1257
1258           unsigned i;
1259
1260           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1261           aop->size = getSize(sym->type);
1262           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1263             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1264
1265           DEBUGpic16_emitcode(";","%d",__LINE__);
1266           return;
1267         }
1268 #endif
1269         /* else spill location  */
1270         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1271             /* force a new aop if sizes differ */
1272             sym->usl.spillLoc->aop = NULL;
1273         }
1274
1275 #if 0
1276         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1277                             __FUNCTION__,__LINE__,
1278                             sym->usl.spillLoc->rname,
1279                             sym->rname, sym->usl.spillLoc->offset);
1280 #endif
1281
1282         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1283         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1284         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1285           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1286                                                   getSize(sym->type), 
1287                                                   sym->usl.spillLoc->offset, op);
1288         } else {
1289           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1290           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1291           assert (getSize(sym->type) <= 1);
1292           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1293         }
1294         aop->size = getSize(sym->type);
1295
1296         return;
1297     }
1298
1299     {
1300       sym_link *type = operandType(op);
1301 #if 0
1302       if(IS_PTR_CONST(type)) 
1303 #else
1304       if(IS_CODEPTR(type)) 
1305 #endif
1306         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1307     }
1308
1309     /* must be in a register */
1310     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1311     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1312     aop->size = sym->nRegs;
1313     for ( i = 0 ; i < sym->nRegs ;i++)
1314         aop->aopu.aop_reg[i] = sym->regs[i];
1315 }
1316
1317 /*-----------------------------------------------------------------*/
1318 /* pic16_freeAsmop - free up the asmop given to an operand               */
1319 /*----------------------------------------------------------------*/
1320 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1321 {   
1322     asmop *aop ;
1323
1324     if (!op)
1325         aop = aaop;
1326     else 
1327         aop = op->aop;
1328
1329     if (!aop)
1330         return ;
1331
1332     if (aop->freed)
1333         goto dealloc; 
1334
1335     aop->freed = 1;
1336
1337     /* depending on the asmop type only three cases need work AOP_RO
1338        , AOP_R1 && AOP_STK */
1339 #if 1
1340     switch (aop->type) {
1341         case AOP_FSR0 :
1342             if (_G.fsr0Pushed ) {
1343                 if (pop) {
1344                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1345                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1346 //                    pic16_emitcode ("pop","ar0");
1347                     _G.fsr0Pushed--;
1348                 }
1349             }
1350             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1351             break;
1352
1353         case AOP_FSR2 :
1354             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1355             break;
1356
1357         case AOP_R0 :
1358             if (_G.r0Pushed ) {
1359                 if (pop) {
1360                     pic16_emitcode ("pop","ar0");     
1361                     _G.r0Pushed--;
1362                 }
1363             }
1364             bitVectUnSetBit(ic->rUsed,R0_IDX);
1365             break;
1366
1367         case AOP_R1 :
1368             if (_G.r1Pushed ) {
1369                 if (pop) {
1370                     pic16_emitcode ("pop","ar1");
1371                     _G.r1Pushed--;
1372                 }
1373             }
1374             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1375             break;
1376
1377         case AOP_STA:
1378           {
1379             int i;
1380
1381               /* we must store the result on stack */
1382               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1383                 // operands on stack are accessible via "FSR2 + index" with index
1384                 // starting at 2 for arguments and growing from 0 downwards for
1385                 // local variables (index == 0 is not assigned so we add one here)
1386                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1387                 if (soffs <= 0) {
1388                   assert (soffs < 0);
1389                   soffs++;
1390                 } // if
1391                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1392                 for(i=0;i<aop->size;i++) {
1393                   /* initialise for stack access via frame pointer */
1394                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1395                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1396                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1397                 }
1398         
1399                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1400               }
1401
1402               if(!_G.resDirect) {
1403                 for(i=0;i<aop->size;i++) {
1404                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1405
1406                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1407                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1408                 }
1409                   
1410               }
1411               _G.resDirect = 0;
1412           }
1413           break;
1414 #if 0
1415         case AOP_STK :
1416         {
1417             int sz = aop->size;    
1418             int stk = aop->aopu.aop_stk + aop->size;
1419             bitVectUnSetBit(ic->rUsed,R0_IDX);
1420             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1421
1422             getFreePtr(ic,&aop,FALSE);
1423             
1424             if (options.stack10bit)
1425             {
1426                 /* I'm not sure what to do here yet... */
1427                 /* #STUB */
1428                 fprintf(stderr, 
1429                         "*** Warning: probably generating bad code for "
1430                         "10 bit stack mode.\n");
1431             }
1432             
1433             if (stk) {
1434                 pic16_emitcode ("mov","a,_bp");
1435                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1436                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1437             } else {
1438                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1439             }
1440
1441             while (sz--) {
1442                 pic16_emitcode("pop","acc");
1443                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1444                 if (!sz) break;
1445                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1446             }
1447             op->aop = aop;
1448             pic16_freeAsmop(op,NULL,ic,TRUE);
1449             if (_G.r0Pushed) {
1450                 pic16_emitcode("pop","ar0");
1451                 _G.r0Pushed--;
1452             }
1453
1454             if (_G.r1Pushed) {
1455                 pic16_emitcode("pop","ar1");
1456                 _G.r1Pushed--;
1457             }       
1458         }
1459 #endif
1460
1461     }
1462 #endif
1463
1464 dealloc:
1465     /* all other cases just dealloc */
1466     if (op ) {
1467         op->aop = NULL;
1468         if (IS_SYMOP(op)) {
1469             OP_SYMBOL(op)->aop = NULL;    
1470             /* if the symbol has a spill */
1471             if (SPIL_LOC(op))
1472                 SPIL_LOC(op)->aop = NULL;
1473         }
1474     }
1475 }
1476
1477 /*-----------------------------------------------------------------*/
1478 /* pic16_aopGet - for fetching value of the aop                          */
1479 /*-----------------------------------------------------------------*/
1480 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1481 {
1482     char *s = buffer ;
1483     char *rs;
1484
1485     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1486
1487     /* offset is greater than size then zero */
1488     if (offset > (aop->size - 1) &&
1489         aop->type != AOP_LIT)
1490         return zero;
1491
1492     /* depending on type */
1493     switch (aop->type) {
1494
1495     case AOP_FSR0:
1496     case AOP_FSR2:
1497       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1498       rs = Safe_calloc(1, strlen(s)+1);
1499       strcpy(rs, s);
1500       return (rs);
1501       
1502 #if 0
1503       /* if we need to increment it */
1504       while (offset > aop->coff)
1505         {
1506           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1507           aop->coff++;
1508         }
1509
1510       while (offset < aop->coff)
1511         {
1512           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1513           aop->coff--;
1514         }
1515       aop->coff = offset;
1516       if (aop->paged)
1517         {
1518           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1519           return (dname ? "acc" : "a");
1520         }
1521       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1522       rs = Safe_calloc (1, strlen (s) + 1);
1523       strcpy (rs, s);
1524       return rs;
1525 #endif
1526
1527         
1528     case AOP_IMMD:
1529         if (bit16) 
1530             sprintf (s,"%s",aop->aopu.aop_immd);
1531         else
1532             if (offset) 
1533                 sprintf(s,"(%s >> %d)",
1534                         aop->aopu.aop_immd,
1535                         offset*8);
1536             else
1537                 sprintf(s,"%s",
1538                         aop->aopu.aop_immd);
1539         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1540         rs = Safe_calloc(1,strlen(s)+1);
1541         strcpy(rs,s);   
1542         return rs;
1543         
1544     case AOP_DIR:
1545       if (offset) {
1546         sprintf(s,"(%s + %d)",
1547                 aop->aopu.aop_dir,
1548                 offset);
1549         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1550       } else
1551             sprintf(s,"%s",aop->aopu.aop_dir);
1552         rs = Safe_calloc(1,strlen(s)+1);
1553         strcpy(rs,s);   
1554         return rs;
1555         
1556     case AOP_REG:
1557       return aop->aopu.aop_reg[offset]->name;
1558         
1559     case AOP_CRY:
1560       return aop->aopu.aop_dir;
1561         
1562     case AOP_ACC:
1563         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1564 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1565 //        assert( 0 );
1566 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1567         rs = Safe_strdup("WREG");
1568         return (rs);
1569
1570     case AOP_LIT:
1571         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1572         rs = Safe_calloc(1,strlen(s)+1);
1573         strcpy(rs,s);   
1574         return rs;
1575         
1576     case AOP_STR:
1577         aop->coff = offset ;
1578
1579 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1580 //          dname)
1581 //          return "acc";
1582         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1583           aop->type = AOP_ACC;
1584           return Safe_strdup("WREG");
1585         }
1586         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1587         
1588         return aop->aopu.aop_str[offset];
1589         
1590     case AOP_PCODE:
1591       {
1592         pCodeOp *pcop = aop->aopu.pcop;
1593         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1594         if(pcop->name) {
1595           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1596           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1597           if (offset) {
1598             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1599           } else {
1600             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1601           }
1602         } else
1603           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1604
1605       }
1606       rs = Safe_calloc(1,strlen(s)+1);
1607       strcpy(rs,s);   
1608       return rs;
1609
1610 #if 0
1611     case AOP_PAGED:
1612       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1613       if (offset) {
1614         sprintf(s,"(%s + %d)",
1615                 aop->aopu.aop_dir,
1616                 offset);
1617       } else
1618             sprintf(s,"%s",aop->aopu.aop_dir);
1619       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1620       rs = Safe_calloc(1,strlen(s)+1);
1621       strcpy(rs,s);   
1622       return rs;
1623 #endif
1624
1625     case AOP_STA:
1626         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1627         return (rs);
1628         
1629     case AOP_STK:
1630 //        pCodeOp *pcop = aop->aop
1631         break;
1632
1633     }
1634
1635     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1636     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1637            "aopget got unsupported aop->type");
1638     exit(0);
1639 }
1640
1641
1642
1643 /* lock has the following meaning: When allocating temporary registers
1644  * for stack variables storage, the value of the temporary register is
1645  * saved on stack. Its value is restored at the end. This procedure is
1646  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1647  * a possibility that before a call to pic16_aopOp, a temporary register
1648  * is allocated for a while and it is freed after some time, this will
1649  * mess the stack and values will not be restored properly. So use lock=1
1650  * to allocate temporary registers used internally by the programmer, and
1651  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1652  * to inform the compiler developer about a possible bug. This is an internal
1653  * feature for developing the compiler -- VR */
1654  
1655 int _TempReg_lock = 0;
1656 /*-----------------------------------------------------------------*/
1657 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1658 /*-----------------------------------------------------------------*/
1659 pCodeOp *pic16_popGetTempReg(int lock)
1660 {
1661   pCodeOp *pcop;
1662   symbol *cfunc;
1663
1664 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1665     if(_TempReg_lock) {
1666 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1667     }
1668     
1669     _TempReg_lock += lock;
1670     
1671     cfunc = currFunc;
1672     currFunc = NULL;
1673
1674     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1675     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1676       PCOR(pcop)->r->wasUsed=1;
1677       PCOR(pcop)->r->isFree=0;
1678
1679       /* push value on stack */
1680       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1681     }
1682
1683     currFunc = cfunc;
1684
1685   return pcop;
1686 }
1687
1688 /*-----------------------------------------------------------------*/
1689 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1690 /*                           is not part of f, but don't save if   */
1691 /*                           inside v                              */
1692 /*-----------------------------------------------------------------*/
1693 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1694 {
1695   pCodeOp *pcop=NULL;
1696   symbol *cfunc;
1697   int i;
1698
1699 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1700
1701     if(_TempReg_lock) {
1702 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1703     }
1704
1705     _TempReg_lock += lock;
1706
1707     cfunc = currFunc;
1708     currFunc = NULL;
1709
1710     i = bitVectFirstBit(f);
1711     while(i < 128) {
1712
1713       /* bypass registers that are used by function */
1714       if(!bitVectBitValue(f, i)) {
1715       
1716         /* bypass registers that are already allocated for stack access */
1717         if(!bitVectBitValue(v, i))  {
1718         
1719 //          debugf("getting register rIdx = %d\n", i);
1720           /* ok, get the operand */
1721           pcop = pic16_newpCodeOpReg( i );
1722     
1723           /* should never by NULL */
1724           assert( pcop != NULL );
1725
1726           
1727           /* sanity check */
1728           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1729             int found=0;
1730             
1731               PCOR(pcop)->r->wasUsed=1;
1732               PCOR(pcop)->r->isFree=0;
1733
1734
1735               {
1736                 regs *sr;
1737               
1738                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1739
1740                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1741                       /* already used in previous steps, break */
1742                       found=1;          
1743                       break;
1744                     }
1745                   }
1746               }
1747
1748               /* caller takes care of the following */
1749 //              bitVectSetBit(v, i);
1750
1751               if(!found) {
1752                 /* push value on stack */
1753                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1754                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1755               }
1756           
1757             break;
1758           }
1759         }
1760       }
1761       i++;
1762     }
1763
1764     currFunc = cfunc;
1765
1766   return pcop;
1767 }
1768
1769
1770 /*-----------------------------------------------------------------*/
1771 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1772 /*-----------------------------------------------------------------*/
1773 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1774 {
1775   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1776
1777   _TempReg_lock -= lock;
1778
1779   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1780     PCOR(pcop)->r->isFree = 1;
1781
1782     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1783   }
1784 }
1785 /*-----------------------------------------------------------------*/
1786 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1787 /*-----------------------------------------------------------------*/
1788 pCodeOp *pic16_popGetLabel(unsigned int key)
1789 {
1790
1791   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1792
1793   if(key>max_key)
1794     max_key = key;
1795
1796   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1797 }
1798
1799 /*-----------------------------------------------------------------*/
1800 /* pic16_popCopyReg - copy a pcode operator                              */
1801 /*-----------------------------------------------------------------*/
1802 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1803 {
1804   pCodeOpReg *pcor;
1805
1806   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1807   memcpy (pcor, pc, sizeof (pCodeOpReg));
1808   pcor->r->wasUsed = 1;
1809   
1810   //pcor->pcop.type = pc->pcop.type;
1811   if(pc->pcop.name) {
1812     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1813       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1814   } else
1815     pcor->pcop.name = NULL;
1816
1817   //pcor->r = pc->r;
1818   //pcor->rIdx = pc->rIdx;
1819   //pcor->r->wasUsed=1;
1820   //pcor->instance = pc->instance;
1821
1822 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1823
1824   return PCOP(pcor);
1825 }
1826
1827 /*-----------------------------------------------------------------*/
1828 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1829 /*-----------------------------------------------------------------*/
1830 pCodeOp *pic16_popGetLit(int lit)
1831 {
1832   return pic16_newpCodeOpLit(lit);
1833 }
1834
1835 /*-----------------------------------------------------------------*/
1836 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1837 /*-----------------------------------------------------------------*/
1838 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1839 {
1840   return pic16_newpCodeOpLit2(lit, arg2);
1841 }
1842
1843
1844 /*-----------------------------------------------------------------*/
1845 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1846 /*-----------------------------------------------------------------*/
1847 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1848 {
1849   return pic16_newpCodeOpImmd(name, offset,index, 0);
1850 }
1851
1852
1853 /*-----------------------------------------------------------------*/
1854 /* pic16_popGet - asm operator to pcode operator conversion              */
1855 /*-----------------------------------------------------------------*/
1856 pCodeOp *pic16_popGetWithString(char *str)
1857 {
1858   pCodeOp *pcop;
1859
1860
1861   if(!str) {
1862     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1863     exit (1);
1864   }
1865
1866   pcop = pic16_newpCodeOp(str,PO_STR);
1867
1868   return pcop;
1869 }
1870
1871 /*-----------------------------------------------------------------*/
1872 /* pic16_popRegFromString -                                        */
1873 /*-----------------------------------------------------------------*/
1874 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1875 {
1876
1877   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1878   pcop->type = PO_DIR;
1879
1880   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1881   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1882
1883   if(!str)
1884     str = "BAD_STRING";
1885
1886   pcop->name = Safe_calloc(1,strlen(str)+1);
1887   strcpy(pcop->name,str);
1888
1889   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1890
1891   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1892
1893   /* make sure that register doesn't exist,
1894    * and operand isn't NULL
1895    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1896   if((PCOR(pcop)->r == NULL) 
1897     && (op)
1898     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1899 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1900 //              __FUNCTION__, __LINE__, str, size, offset);
1901
1902     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1903     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1904
1905   }
1906   PCOR(pcop)->instance = offset;
1907
1908   return pcop;
1909 }
1910
1911 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1912 {
1913   pCodeOp *pcop;
1914
1915 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1916
1917         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1918         PCOR(pcop)->rIdx = rIdx;
1919         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1920
1921         PCOR(pcop)->r->isFree = 0;
1922         PCOR(pcop)->r->wasUsed = 1;
1923
1924         pcop->type = PCOR(pcop)->r->pc_type;
1925
1926   return pcop;
1927 }
1928
1929 /*---------------------------------------------------------------------------------*/
1930 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1931 /*                 VR 030601                                                       */
1932 /*---------------------------------------------------------------------------------*/
1933 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1934 {
1935   pCodeOpReg2 *pcop2;
1936   pCodeOp *temp;
1937   
1938         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1939
1940         /* comment the following check, so errors to throw up */
1941 //      if(!pcop2)return NULL;
1942
1943         temp = pic16_popGet(aop_dst, offset);
1944         pcop2->pcop2 = temp;
1945         
1946   return PCOP(pcop2);
1947 }
1948
1949
1950
1951 /*--------------------------------------------------------------------------------.-*/
1952 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1953 /*                  VR 030601 , adapted by Hans Dorn                                */
1954 /*--------------------------------------------------------------------------------.-*/
1955 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1956 {
1957   pCodeOpReg2 *pcop2;
1958  
1959         pcop2 = (pCodeOpReg2 *)src;
1960         pcop2->pcop2 = dst;
1961         
1962         return PCOP(pcop2);
1963 }
1964
1965
1966
1967 /*---------------------------------------------------------------------------------*/
1968 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1969 /*                     movff instruction                                           */
1970 /*---------------------------------------------------------------------------------*/
1971 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1972 {
1973   pCodeOpReg2 *pcop2;
1974
1975         if(!noalloc) {
1976                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1977                 pcop2->pcop2 = pic16_popCopyReg(dst);
1978         } else {
1979                 /* the pCodeOp may be already allocated */
1980                 pcop2 = (pCodeOpReg2 *)(src);
1981                 pcop2->pcop2 = (pCodeOp *)(dst);
1982         }
1983
1984   return PCOP(pcop2);
1985 }
1986
1987
1988 /*-----------------------------------------------------------------*/
1989 /* pic16_popGet - asm operator to pcode operator conversion              */
1990 /*-----------------------------------------------------------------*/
1991 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1992 {
1993   //char *s = buffer ;
1994   char *rs;
1995   pCodeOp *pcop;
1996
1997     FENTRY2;
1998     /* offset is greater than
1999     size then zero */
2000
2001 //    if (offset > (aop->size - 1) &&
2002 //        aop->type != AOP_LIT)
2003 //      return NULL;  //zero;
2004
2005     /* depending on type */
2006     switch (aop->type) {
2007         
2008     case AOP_R0:
2009     case AOP_R1:
2010     case AOP_DPTR:
2011     case AOP_DPTR2:
2012         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2013         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2014         assert( 0 );
2015         return NULL;
2016
2017
2018     case AOP_FSR0:
2019     case AOP_FSR2:
2020       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2021       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2022       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2023       PCOR(pcop)->r->wasUsed = 1;
2024       PCOR(pcop)->r->isFree = 0;
2025       
2026       PCOR(pcop)->instance = offset;
2027       pcop->type = PCOR(pcop)->r->pc_type;
2028       return (pcop);
2029
2030     case AOP_IMMD:
2031       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2032       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2033
2034     case AOP_STA:
2035       /* pCodeOp is already allocated from aopForSym */
2036         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2037         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2038           
2039       return (pcop);
2040       
2041     case AOP_ACC:
2042       {
2043         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2044
2045         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2046
2047         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2048         
2049         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2050         PCOR(pcop)->rIdx = rIdx;
2051         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2052         PCOR(pcop)->r->wasUsed=1;
2053         PCOR(pcop)->r->isFree=0;
2054
2055         PCOR(pcop)->instance = offset;
2056         pcop->type = PCOR(pcop)->r->pc_type;
2057 //      rs = aop->aopu.aop_reg[offset]->name;
2058 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2059         return pcop;
2060
2061
2062 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2063 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2064
2065 //      assert( 0 );
2066       }
2067         
2068     case AOP_DIR:
2069       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2070       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2071         
2072 #if 0
2073     case AOP_PAGED:
2074       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2075       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2076 #endif
2077
2078     case AOP_REG:
2079       {
2080         int rIdx;
2081         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2082         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2083
2084         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2085         
2086         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2087 //      pcop->type = PO_GPR_REGISTER;
2088         PCOR(pcop)->rIdx = rIdx;
2089         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2090         PCOR(pcop)->r->wasUsed=1;
2091         PCOR(pcop)->r->isFree=0;
2092
2093         PCOR(pcop)->instance = offset;
2094         pcop->type = PCOR(pcop)->r->pc_type;
2095         
2096         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2097         rs = aop->aopu.aop_reg[offset]->name;
2098         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2099         return pcop;
2100       }
2101
2102     case AOP_CRY:
2103         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2104
2105       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2106       PCOR(pcop)->instance = offset;
2107       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2108       //if(PCOR(pcop)->r == NULL)
2109       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2110       return pcop;
2111         
2112     case AOP_LIT:
2113         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2114       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2115
2116     case AOP_STR:
2117       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2118       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2119
2120       /*
2121       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2122       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2123       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2124       pcop->type = PCOR(pcop)->r->pc_type;
2125       pcop->name = PCOR(pcop)->r->name;
2126
2127       return pcop;
2128       */
2129
2130     case AOP_PCODE:
2131       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2132                           __LINE__, 
2133                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2134       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2135       switch( aop->aopu.pcop->type ) {
2136         case PO_DIR: PCOR(pcop)->instance += offset; break;
2137         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2138         case PO_WREG:
2139             assert (offset==0);
2140             break;
2141         default:
2142           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2143           assert( 0 );  /* should never reach here */;
2144       }
2145       return pcop;
2146     }
2147
2148     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2149            "pic16_popGet got unsupported aop->type");
2150     exit(0);
2151 }
2152 /*-----------------------------------------------------------------*/
2153 /* pic16_aopPut - puts a string for a aop                                */
2154 /*-----------------------------------------------------------------*/
2155 void pic16_aopPut (asmop *aop, char *s, int offset)
2156 {
2157     char *d = buffer ;
2158     symbol *lbl ;
2159
2160     return;
2161
2162     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2163
2164     if (aop->size && offset > ( aop->size - 1)) {
2165         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2166                "pic16_aopPut got offset > aop->size");
2167         exit(0);
2168     }
2169
2170     /* will assign value to value */
2171     /* depending on where it is ofcourse */
2172     switch (aop->type) {
2173     case AOP_DIR:
2174       if (offset) {
2175         sprintf(d,"(%s + %d)",
2176                 aop->aopu.aop_dir,offset);
2177         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2178
2179       } else
2180             sprintf(d,"%s",aop->aopu.aop_dir);
2181         
2182         if (strcmp(d,s)) {
2183           DEBUGpic16_emitcode(";","%d",__LINE__);
2184           if(strcmp(s,"W"))
2185             pic16_emitcode("movf","%s,w",s);
2186           pic16_emitcode("movwf","%s",d);
2187
2188           if(strcmp(s,"W")) {
2189             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2190             if(offset >= aop->size) {
2191               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2192               break;
2193             } else
2194               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2195           }
2196
2197           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2198
2199
2200         }
2201         break;
2202         
2203     case AOP_REG:
2204       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2205         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2206           /*
2207             if (*s == '@'           ||
2208                 strcmp(s,"r0") == 0 ||
2209                 strcmp(s,"r1") == 0 ||
2210                 strcmp(s,"r2") == 0 ||
2211                 strcmp(s,"r3") == 0 ||
2212                 strcmp(s,"r4") == 0 ||
2213                 strcmp(s,"r5") == 0 ||
2214                 strcmp(s,"r6") == 0 || 
2215                 strcmp(s,"r7") == 0 )
2216                 pic16_emitcode("mov","%s,%s  ; %d",
2217                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2218             else
2219           */
2220
2221           if(strcmp(s,"W")==0 )
2222             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2223
2224           pic16_emitcode("movwf","%s",
2225                    aop->aopu.aop_reg[offset]->name);
2226
2227           if(strcmp(s,zero)==0) {
2228             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2229
2230           } else if(strcmp(s,"W")==0) {
2231             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2232             pcop->type = PO_GPR_REGISTER;
2233
2234             PCOR(pcop)->rIdx = -1;
2235             PCOR(pcop)->r = NULL;
2236
2237             DEBUGpic16_emitcode(";","%d",__LINE__);
2238             pcop->name = Safe_strdup(s);
2239             pic16_emitpcode(POC_MOVFW,pcop);
2240             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2241           } else if(strcmp(s,one)==0) {
2242             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2243             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2244           } else {
2245             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2246           }
2247         }
2248         break;
2249         
2250     case AOP_DPTR:
2251     case AOP_DPTR2:
2252     
2253     if (aop->type == AOP_DPTR2)
2254     {
2255         genSetDPTR(1);
2256     }
2257     
2258         if (aop->code) {
2259             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2260                    "pic16_aopPut writting to code space");
2261             exit(0);
2262         }
2263         
2264         while (offset > aop->coff) {
2265             aop->coff++;
2266             pic16_emitcode ("inc","dptr");
2267         }
2268         
2269         while (offset < aop->coff) {
2270             aop->coff-- ;
2271             pic16_emitcode("lcall","__decdptr");
2272         }
2273         
2274         aop->coff = offset;
2275         
2276         /* if not in accumulater */
2277         MOVA(s);        
2278         
2279         pic16_emitcode ("movx","@dptr,a");
2280         
2281     if (aop->type == AOP_DPTR2)
2282     {
2283         genSetDPTR(0);
2284     }
2285         break;
2286         
2287     case AOP_R0:
2288     case AOP_R1:
2289         while (offset > aop->coff) {
2290             aop->coff++;
2291             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2292         }
2293         while (offset < aop->coff) {
2294             aop->coff-- ;
2295             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2296         }
2297         aop->coff = offset;
2298         
2299         if (aop->paged) {
2300             MOVA(s);           
2301             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2302             
2303         } else
2304             if (*s == '@') {
2305                 MOVA(s);
2306                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2307             } else
2308                 if (strcmp(s,"r0") == 0 ||
2309                     strcmp(s,"r1") == 0 ||
2310                     strcmp(s,"r2") == 0 ||
2311                     strcmp(s,"r3") == 0 ||
2312                     strcmp(s,"r4") == 0 ||
2313                     strcmp(s,"r5") == 0 ||
2314                     strcmp(s,"r6") == 0 || 
2315                     strcmp(s,"r7") == 0 ) {
2316                     char buffer[10];
2317                     sprintf(buffer,"a%s",s);
2318                     pic16_emitcode("mov","@%s,%s",
2319                              aop->aopu.aop_ptr->name,buffer);
2320                 } else
2321                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2322         
2323         break;
2324         
2325     case AOP_STK:
2326         if (strcmp(s,"a") == 0)
2327             pic16_emitcode("push","acc");
2328         else
2329             pic16_emitcode("push","%s",s);
2330         
2331         break;
2332         
2333     case AOP_CRY:
2334         /* if bit variable */
2335         if (!aop->aopu.aop_dir) {
2336             pic16_emitcode("clr","a");
2337             pic16_emitcode("rlc","a");
2338         } else {
2339             if (s == zero) 
2340                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2341             else
2342                 if (s == one)
2343                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2344                 else
2345                     if (!strcmp(s,"c"))
2346                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2347                     else {
2348                         lbl = newiTempLabel(NULL);
2349                         
2350                         if (strcmp(s,"a")) {
2351                             MOVA(s);
2352                         }
2353                         pic16_emitcode("clr","c");
2354                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2355                         pic16_emitcode("cpl","c");
2356                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2357                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2358                     }
2359         }
2360         break;
2361         
2362     case AOP_STR:
2363         aop->coff = offset;
2364         if (strcmp(aop->aopu.aop_str[offset],s))
2365             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2366         break;
2367         
2368     case AOP_ACC:
2369         aop->coff = offset;
2370         if (!offset && (strcmp(s,"acc") == 0))
2371             break;
2372         
2373         if (strcmp(aop->aopu.aop_str[offset],s))
2374             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2375         break;
2376
2377     default :
2378         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2379 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2380 //             "pic16_aopPut got unsupported aop->type");
2381 //      exit(0);    
2382     }    
2383
2384 }
2385
2386 /*-----------------------------------------------------------------*/
2387 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2388 /*-----------------------------------------------------------------*/
2389 void pic16_mov2w (asmop *aop, int offset)
2390 {
2391   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2392
2393   if(is_LitAOp(aop))
2394     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2395   else
2396     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2397 }
2398
2399 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2400 {
2401   if(is_LitAOp(src)) {
2402     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2403     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2404   } else {
2405     if(pic16_sameRegsOfs(src, dst, offset))return;
2406     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2407                       pic16_popGet(dst, offset)));
2408   }
2409 }
2410
2411 static void pic16_movLit2f(pCodeOp *pc, int lit)
2412 {
2413   if (0 == (lit & 0x00ff))
2414   {
2415     pic16_emitpcode (POC_CLRF, pc);
2416   } else if (0xff == (lit & 0x00ff))
2417   {
2418     pic16_emitpcode (POC_SETF, pc);
2419   } else {
2420     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2421     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2422   }
2423 }
2424
2425 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2426 {
2427   if(is_LitAOp(src)) {
2428     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2429     pic16_emitpcode(POC_MOVWF, dst);
2430   } else {
2431     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2432   }
2433 }
2434
2435 void pic16_testStackOverflow(void)
2436 {
2437 #define GSTACK_TEST_NAME        "_gstack_test"
2438
2439   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2440   
2441   {
2442     symbol *sym;
2443
2444       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2445       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2446 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2447       checkAddSym(&externs, sym);
2448   }
2449
2450 }
2451
2452 /* push pcop into stack */
2453 void pic16_pushpCodeOp(pCodeOp *pcop)
2454 {
2455 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2456   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2457   if(pic16_options.gstack)
2458     pic16_testStackOverflow();
2459     
2460 }
2461
2462 /* pop pcop from stack */
2463 void pic16_poppCodeOp(pCodeOp *pcop)
2464 {
2465   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2466   if(pic16_options.gstack)
2467     pic16_testStackOverflow();
2468 }
2469
2470
2471 /*-----------------------------------------------------------------*/
2472 /* pushw - pushes wreg to stack                                    */
2473 /*-----------------------------------------------------------------*/
2474 void pushw(void)
2475 {
2476   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2477   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2478   if(pic16_options.gstack)
2479     pic16_testStackOverflow();
2480 }
2481
2482                 
2483 /*-----------------------------------------------------------------*/
2484 /* pushaop - pushes aop to stack                                   */
2485 /*-----------------------------------------------------------------*/
2486 void pushaop(asmop *aop, int offset)
2487 {
2488   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2489
2490   if(is_LitAOp(aop)) {
2491     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2492     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2493   } else {
2494     pic16_emitpcode(POC_MOVFF,
2495       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2496   }
2497
2498   if(pic16_options.gstack)
2499     pic16_testStackOverflow();
2500 }
2501
2502 /*-----------------------------------------------------------------*/
2503 /* popaop - pops aop from stack                                    */
2504 /*-----------------------------------------------------------------*/
2505 void popaop(asmop *aop, int offset)
2506 {
2507   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2508   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2509   if(pic16_options.gstack)
2510     pic16_testStackOverflow();
2511 }
2512
2513 void popaopidx(asmop *aop, int offset, int index)
2514 {
2515   int ofs=1;
2516
2517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2518
2519     if(STACK_MODEL_LARGE)ofs++;
2520
2521     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2522     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2523     if(pic16_options.gstack)
2524       pic16_testStackOverflow();
2525 }
2526
2527 #if !(USE_GENERIC_SIGNED_SHIFT)
2528 /*-----------------------------------------------------------------*/
2529 /* reAdjustPreg - points a register back to where it should        */
2530 /*-----------------------------------------------------------------*/
2531 static void reAdjustPreg (asmop *aop)
2532 {
2533     int size ;
2534
2535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2536     aop->coff = 0;
2537     if ((size = aop->size) <= 1)
2538         return ;
2539     size-- ;
2540     switch (aop->type) {
2541         case AOP_R0 :
2542         case AOP_R1 :
2543             while (size--)
2544                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2545             break;          
2546         case AOP_DPTR :
2547         case AOP_DPTR2:
2548             if (aop->type == AOP_DPTR2)
2549             {
2550                 genSetDPTR(1);
2551             } 
2552             while (size--)
2553             {
2554                 pic16_emitcode("lcall","__decdptr");
2555             }
2556                 
2557             if (aop->type == AOP_DPTR2)
2558             {
2559                 genSetDPTR(0);
2560             }                
2561             break;  
2562
2563     }   
2564
2565 }
2566 #endif
2567
2568 #if 0
2569 /*-----------------------------------------------------------------*/
2570 /* opIsGptr: returns non-zero if the passed operand is             */   
2571 /* a generic pointer type.                                         */
2572 /*-----------------------------------------------------------------*/ 
2573 static int opIsGptr(operand *op)
2574 {
2575     sym_link *type = operandType(op);
2576     
2577     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2578     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2579     {
2580         return 1;
2581     }
2582     return 0;        
2583 }
2584 #endif
2585
2586 /*-----------------------------------------------------------------*/
2587 /* pic16_getDataSize - get the operand data size                         */
2588 /*-----------------------------------------------------------------*/
2589 int pic16_getDataSize(operand *op)
2590 {
2591     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2592
2593
2594     return AOP_SIZE(op);
2595
2596     // tsd- in the pic port, the genptr size is 1, so this code here
2597     // fails. ( in the 8051 port, the size was 4).
2598 #if 0
2599     int size;
2600     size = AOP_SIZE(op);
2601     if (size == GPTRSIZE)
2602     {
2603         sym_link *type = operandType(op);
2604         if (IS_GENPTR(type))
2605         {
2606             /* generic pointer; arithmetic operations
2607              * should ignore the high byte (pointer type).
2608              */
2609             size--;
2610     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2611         }
2612     }
2613     return size;
2614 #endif
2615 }
2616
2617 /*-----------------------------------------------------------------*/
2618 /* pic16_outAcc - output Acc                                             */
2619 /*-----------------------------------------------------------------*/
2620 void pic16_outAcc(operand *result)
2621 {
2622   int size,offset;
2623   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2624   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2625
2626
2627   size = pic16_getDataSize(result);
2628   if(size){
2629     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2630     size--;
2631     offset = 1;
2632     /* unsigned or positive */
2633     while(size--)
2634       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2635   }
2636
2637 }
2638
2639 /*-----------------------------------------------------------------*/
2640 /* pic16_outBitC - output a bit C                                  */
2641 /*                 Move to result the value of Carry flag -- VR    */
2642 /*-----------------------------------------------------------------*/
2643 void pic16_outBitC(operand *result)
2644 {
2645   int i;
2646
2647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2648
2649     /* if the result is bit */
2650     if (AOP_TYPE(result) == AOP_CRY) {
2651         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2652         pic16_aopPut(AOP(result),"c",0);
2653     } else {
2654
2655         i = AOP_SIZE(result);
2656         while(i--) {
2657                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2658         }
2659         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2660     }
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_outBitOp - output a bit from Op                           */
2665 /*                 Move to result the value of set/clr op -- VR    */
2666 /*-----------------------------------------------------------------*/
2667 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2668 {
2669   int i;
2670
2671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2672
2673     /* if the result is bit */
2674     if (AOP_TYPE(result) == AOP_CRY) {
2675         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2676         pic16_aopPut(AOP(result),"c",0);
2677     } else {
2678
2679         i = AOP_SIZE(result);
2680         while(i--) {
2681                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2682         }
2683         pic16_emitpcode(POC_RRCF, pcop);          
2684         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2685     }
2686 }
2687
2688 /*-----------------------------------------------------------------*/
2689 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2690 /*-----------------------------------------------------------------*/
2691 void pic16_toBoolean(operand *oper)
2692 {
2693     int size = AOP_SIZE(oper) - 1;
2694     int offset = 1;
2695
2696     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2697
2698     if ( AOP_TYPE(oper) != AOP_ACC) {
2699       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2700     }
2701     while (size--) {
2702       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2703     }
2704 }
2705
2706 /*-----------------------------------------------------------------*/
2707 /* genUminusFloat - unary minus for floating points                */
2708 /*-----------------------------------------------------------------*/
2709 static void genUminusFloat(operand *op,operand *result)
2710 {
2711   int size ,offset =0 ;
2712   
2713     FENTRY;
2714     /* for this we just need to flip the 
2715     first it then copy the rest in place */
2716     size = AOP_SIZE(op);
2717     assert( size == AOP_SIZE(result) );
2718
2719     while(size--) {
2720       pic16_mov2f(AOP(result), AOP(op), offset);
2721       offset++;
2722     }
2723     
2724     /* toggle the MSB's highest bit */
2725     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2726 }
2727
2728 /*-----------------------------------------------------------------*/
2729 /* genUminus - unary minus code generation                         */
2730 /*-----------------------------------------------------------------*/
2731 static void genUminus (iCode *ic)
2732 {
2733   int size, i;
2734   sym_link *optype, *rtype;
2735   symbol *label;
2736   int needLabel=0;
2737
2738     FENTRY;     
2739     
2740     /* assign asmops */
2741     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2742     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2743
2744     /* if both in bit space then special case */
2745     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2746       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2747         
2748         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2749         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2750         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2751         goto release; 
2752     } 
2753
2754     optype = operandType(IC_LEFT(ic));
2755     rtype = operandType(IC_RESULT(ic));
2756
2757
2758     /* if float then do float stuff */
2759     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2760       if(IS_FIXED(optype))
2761         debugf("implement fixed16x16 type\n", 0);
2762         
2763         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2764         goto release;
2765     }
2766
2767     /* otherwise subtract from zero by taking the 2's complement */
2768     size = AOP_SIZE(IC_LEFT(ic));
2769     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2770     label = newiTempLabel ( NULL );
2771     
2772     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2773       for (i=size-1; i > 0; i--) {
2774         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2775       } // for
2776       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2777       for (i=1; i < size; i++) {
2778         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2779         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2780       } // for
2781     } else {
2782       for (i=size-1; i >= 0; i--) {
2783         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2784         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2785       } // for
2786       if (size > 1) {
2787         for (i=0; i < size-2; i++) {
2788           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2789           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2790         } // for
2791         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2792       } // if
2793       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2794     }
2795     if (needLabel)
2796       pic16_emitpLabel (label->key);
2797
2798 release:
2799     /* release the aops */
2800     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2801     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2802 }
2803
2804 #if 0
2805 /*-----------------------------------------------------------------*/
2806 /* saveRegisters - will look for a call and save the registers     */
2807 /*-----------------------------------------------------------------*/
2808 static void saveRegisters(iCode *lic) 
2809 {
2810     int i;
2811     iCode *ic;
2812     bitVect *rsave;
2813     sym_link *dtype;
2814
2815     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2816     /* look for call */
2817     for (ic = lic ; ic ; ic = ic->next) 
2818         if (ic->op == CALL || ic->op == PCALL)
2819             break;
2820
2821     if (!ic) {
2822         fprintf(stderr,"found parameter push with no function call\n");
2823         return ;
2824     }
2825
2826     /* if the registers have been saved already then
2827     do nothing */
2828     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2829         return ;
2830
2831     /* find the registers in use at this time 
2832     and push them away to safety */
2833     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2834                           ic->rUsed);
2835
2836     ic->regsSaved = 1;
2837     if (options.useXstack) {
2838         if (bitVectBitValue(rsave,R0_IDX))
2839             pic16_emitcode("mov","b,r0");
2840         pic16_emitcode("mov","r0,%s",spname);
2841         for (i = 0 ; i < pic16_nRegs ; i++) {
2842             if (bitVectBitValue(rsave,i)) {
2843                 if (i == R0_IDX)
2844                     pic16_emitcode("mov","a,b");
2845                 else
2846                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2847                 pic16_emitcode("movx","@r0,a");
2848                 pic16_emitcode("inc","r0");
2849             }
2850         }
2851         pic16_emitcode("mov","%s,r0",spname);
2852         if (bitVectBitValue(rsave,R0_IDX))
2853             pic16_emitcode("mov","r0,b");           
2854     }// else
2855     //for (i = 0 ; i < pic16_nRegs ; i++) {
2856     //    if (bitVectBitValue(rsave,i))
2857     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2858     //}
2859
2860     dtype = operandType(IC_LEFT(ic));
2861     if (currFunc && dtype && 
2862         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2863         IFFUNC_ISISR(currFunc->type) &&
2864         !ic->bankSaved) 
2865
2866         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2867
2868 }
2869 /*-----------------------------------------------------------------*/
2870 /* unsaveRegisters - pop the pushed registers                      */
2871 /*-----------------------------------------------------------------*/
2872 static void unsaveRegisters (iCode *ic)
2873 {
2874     int i;
2875     bitVect *rsave;
2876
2877     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2878     /* find the registers in use at this time 
2879     and push them away to safety */
2880     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2881                           ic->rUsed);
2882     
2883     if (options.useXstack) {
2884         pic16_emitcode("mov","r0,%s",spname);   
2885         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2886             if (bitVectBitValue(rsave,i)) {
2887                 pic16_emitcode("dec","r0");
2888                 pic16_emitcode("movx","a,@r0");
2889                 if (i == R0_IDX)
2890                     pic16_emitcode("mov","b,a");
2891                 else
2892                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2893             }       
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 =  pic16_nRegs ; i >= 0 ; i--) {
2901     //    if (bitVectBitValue(rsave,i))
2902     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2903     //}
2904
2905 }  
2906 #endif
2907
2908 #if 0  // patch 14
2909 /*-----------------------------------------------------------------*/
2910 /* pushSide -                                                      */
2911 /*-----------------------------------------------------------------*/
2912 static void pushSide(operand * oper, int size)
2913 {
2914         int offset = 0;
2915     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2916         while (size--) {
2917                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2918                 if (AOP_TYPE(oper) != AOP_REG &&
2919                     AOP_TYPE(oper) != AOP_DIR &&
2920                     strcmp(l,"a") ) {
2921                         pic16_emitcode("mov","a,%s",l);
2922                         pic16_emitcode("push","acc");
2923                 } else
2924                         pic16_emitcode("push","%s",l);
2925         }
2926 }
2927 #endif // patch 14
2928
2929 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2930 {
2931   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2932     pic16_emitpcode(POC_MOVFW, src);
2933     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2934   } else {
2935     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2936         src, pic16_popGet(AOP(op), offset)));
2937   }
2938 }
2939
2940
2941 /*-----------------------------------------------------------------*/
2942 /* assignResultValue - assign results to oper, rescall==1 is       */
2943 /*                     called from genCall() or genPcall()         */
2944 /*-----------------------------------------------------------------*/
2945 static void assignResultValue(operand * oper, int rescall)
2946 {
2947   int size = AOP_SIZE(oper);
2948   int offset=0;
2949   
2950     FENTRY2;
2951 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2952     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2953
2954     if(rescall) {
2955       /* assign result from a call/pcall function() */
2956                 
2957       /* function results are stored in a special order,
2958        * see top of file with Function return policy, or manual */
2959
2960       if(size <= 4) {
2961         /* 8-bits, result in WREG */
2962         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2963                         
2964         if(size>1) {
2965           /* 16-bits, result in PRODL:WREG */
2966           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2967         }
2968                         
2969         if(size>2) {
2970           /* 24-bits, result in PRODH:PRODL:WREG */
2971           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2972         }
2973                         
2974         if(size>3) {
2975           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2976           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2977         }
2978       
2979       } else {
2980         /* >32-bits, result on stack, and FSR0 points to beginning.
2981          * Fix stack when done */
2982         /* FIXME FIXME */
2983 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2984         while (size--) {
2985 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2986 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2987                 
2988           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2989           GpsuedoStkPtr++;
2990         }
2991                         
2992         /* fix stack */
2993         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2994         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2995         if(STACK_MODEL_LARGE) {
2996           emitSKPNC;
2997           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2998         }
2999       }                 
3000     } else {
3001       int areg = 0;             /* matching argument register */
3002       
3003 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3004       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3005
3006
3007       /* its called from genReceive (probably) -- VR */
3008       /* I hope this code will not be called from somewhere else in the future! 
3009        * We manually set the pseudo stack pointer in genReceive. - dw
3010        */
3011       if(!GpsuedoStkPtr && _G.useWreg) {
3012 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3013
3014         /* The last byte in the assignment is in W */
3015         if(areg <= GpsuedoStkPtr) {
3016           size--;
3017           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3018           offset++;
3019 //          debugf("receive from WREG\n", 0);
3020         }
3021         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3022       }
3023 //      GpsuedoStkPtr++;
3024       _G.stack_lat = AOP_SIZE(oper)-1;
3025
3026       while (size) {
3027         size--;
3028         GpsuedoStkPtr++;
3029         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3030 //        debugf("receive from STACK\n", 0);
3031         offset++;
3032       }
3033     }
3034 }
3035
3036
3037 /*-----------------------------------------------------------------*/
3038 /* genIpush - generate code for pushing this gets a little complex */
3039 /*-----------------------------------------------------------------*/
3040 static void genIpush (iCode *ic)
3041 {
3042 //  int size, offset=0;
3043
3044   FENTRY;
3045   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3046
3047   if(ic->parmPush) {
3048     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3049
3050     /* send to stack as normal */
3051     addSet(&_G.sendSet,ic);
3052 //    addSetHead(&_G.sendSet,ic);
3053     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3054   }
3055
3056         
3057 #if 0
3058     int size, offset = 0 ;
3059     char *l;
3060
3061
3062     /* if this is not a parm push : ie. it is spill push 
3063     and spill push is always done on the local stack */
3064     if (!ic->parmPush) {
3065
3066         /* and the item is spilt then do nothing */
3067         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3068             return ;
3069
3070         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3071         size = AOP_SIZE(IC_LEFT(ic));
3072         /* push it on the stack */
3073         while(size--) {
3074             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3075             if (*l == '#') {
3076                 MOVA(l);
3077                 l = "acc";
3078             }
3079             pic16_emitcode("push","%s",l);
3080         }
3081         return ;        
3082     }
3083
3084     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3085 #endif
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* genIpop - recover the registers: can happen only for spilling   */
3090 /*-----------------------------------------------------------------*/
3091 static void genIpop (iCode *ic)
3092 {
3093   FENTRY;
3094   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3095 #if 0
3096     int size,offset ;
3097
3098
3099     /* if the temp was not pushed then */
3100     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3101         return ;
3102
3103     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3104     size = AOP_SIZE(IC_LEFT(ic));
3105     offset = (size-1);
3106     while (size--) 
3107         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3108                                    FALSE,TRUE));
3109
3110     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3111 #endif
3112 }
3113
3114 #if 0
3115 /*-----------------------------------------------------------------*/
3116 /* unsaverbank - restores the resgister bank from stack            */
3117 /*-----------------------------------------------------------------*/
3118 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3119 {
3120   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3121 #if 0
3122     int i;
3123     asmop *aop ;
3124     regs *r = NULL;
3125
3126     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3127     if (popPsw) {
3128         if (options.useXstack) {
3129             aop = newAsmop(0);
3130             r = getFreePtr(ic,&aop,FALSE);
3131             
3132             
3133             pic16_emitcode("mov","%s,_spx",r->name);
3134             pic16_emitcode("movx","a,@%s",r->name);
3135             pic16_emitcode("mov","psw,a");
3136             pic16_emitcode("dec","%s",r->name);
3137             
3138         }else
3139             pic16_emitcode ("pop","psw");
3140     }
3141
3142     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3143         if (options.useXstack) {       
3144             pic16_emitcode("movx","a,@%s",r->name);
3145             //pic16_emitcode("mov","(%s+%d),a",
3146             //       regspic16[i].base,8*bank+regspic16[i].offset);
3147             pic16_emitcode("dec","%s",r->name);
3148
3149         } else 
3150           pic16_emitcode("pop",""); //"(%s+%d)",
3151         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3152     }
3153
3154     if (options.useXstack) {
3155
3156         pic16_emitcode("mov","_spx,%s",r->name);
3157         pic16_freeAsmop(NULL,aop,ic,TRUE);
3158
3159     }
3160 #endif 
3161 }
3162
3163 /*-----------------------------------------------------------------*/
3164 /* saverbank - saves an entire register bank on the stack          */
3165 /*-----------------------------------------------------------------*/
3166 static void saverbank (int bank, iCode *ic, bool pushPsw)
3167 {
3168   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3169 #if 0
3170     int i;
3171     asmop *aop ;
3172     regs *r = NULL;
3173
3174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3175     if (options.useXstack) {
3176
3177         aop = newAsmop(0);
3178         r = getFreePtr(ic,&aop,FALSE);  
3179         pic16_emitcode("mov","%s,_spx",r->name);
3180
3181     }
3182
3183     for (i = 0 ; i < pic16_nRegs ;i++) {
3184         if (options.useXstack) {
3185             pic16_emitcode("inc","%s",r->name);
3186             //pic16_emitcode("mov","a,(%s+%d)",
3187             //         regspic16[i].base,8*bank+regspic16[i].offset);
3188             pic16_emitcode("movx","@%s,a",r->name);           
3189         } else 
3190           pic16_emitcode("push","");// "(%s+%d)",
3191                      //regspic16[i].base,8*bank+regspic16[i].offset);
3192     }
3193     
3194     if (pushPsw) {
3195         if (options.useXstack) {
3196             pic16_emitcode("mov","a,psw");
3197             pic16_emitcode("movx","@%s,a",r->name);     
3198             pic16_emitcode("inc","%s",r->name);
3199             pic16_emitcode("mov","_spx,%s",r->name);       
3200             pic16_freeAsmop (NULL,aop,ic,TRUE);
3201             
3202         } else
3203             pic16_emitcode("push","psw");
3204         
3205         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3206     }
3207     ic->bankSaved = 1;
3208 #endif
3209 }
3210 #endif  /* 0 */
3211
3212
3213 static int wparamCmp(void *p1, void *p2)
3214 {
3215   return (!strcmp((char *)p1, (char *)p2));
3216 }
3217
3218 int inWparamList(char *s)
3219 {
3220   return isinSetWith(wparamList, s, wparamCmp);
3221
3222
3223
3224 /*-----------------------------------------------------------------*/
3225 /* genCall - generates a call statement                            */
3226 /*-----------------------------------------------------------------*/
3227 static void genCall (iCode *ic)
3228 {
3229   sym_link *ftype;   
3230   int stackParms=0;
3231   int use_wreg=0;
3232   int inwparam=0;
3233   char *fname;
3234   
3235     FENTRY;
3236
3237     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3238     /* if caller saves & we have not saved then */
3239 //    if (!ic->regsSaved)
3240 //      saveRegisters(ic);
3241
3242         /* initialise stackParms for IPUSH pushes */
3243 //      stackParms = psuedoStkPtr;
3244 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3245     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3246     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3247
3248 #if 0
3249     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3250 #endif
3251
3252     /* if send set is not empty the assign */
3253     if (_G.sendSet) {
3254       iCode *sic;
3255       int psuedoStkPtr=-1; 
3256       int firstTimeThruLoop = 1;
3257
3258
3259         /* reverse sendSet if function is not reentrant */
3260         if(!IFFUNC_ISREENT(ftype))
3261           _G.sendSet = reverseSet(_G.sendSet);
3262
3263         /* First figure how many parameters are getting passed */
3264         stackParms = 0;
3265         use_wreg = 0;
3266         
3267         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3268           int size;
3269 //          int offset = 0;
3270
3271             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3272             size = AOP_SIZE(IC_LEFT(sic));
3273
3274             stackParms += size;
3275
3276             /* pass the last byte through WREG */
3277             if(inwparam) {
3278
3279               while (size--) {
3280                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3281                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3282                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3283
3284                 if(!firstTimeThruLoop) {
3285                   /* If this is not the first time we've been through the loop
3286                    * then we need to save the parameter in a temporary
3287                    * register. The last byte of the last parameter is
3288                    * passed in W. */
3289
3290                   pushw();
3291 //                  --psuedoStkPtr;             // sanity check
3292                   use_wreg = 1;
3293                 }
3294                 
3295                 firstTimeThruLoop=0;
3296
3297                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3298
3299 //                offset++;
3300               }
3301             } else {
3302               /* all arguments are passed via stack */
3303               use_wreg = 0;
3304
3305               while (size--) {
3306                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3307                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3308                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3309
3310 //                pushaop(AOP(IC_LEFT(sic)), size);
3311                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3312
3313                 if(!_G.resDirect)
3314                   pushw();
3315               }
3316             }
3317
3318             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3319           }
3320
3321           if(inwparam) {
3322             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3323               pushw();  /* save last parameter to stack if functions has varargs */
3324               use_wreg = 0;
3325             } else
3326               use_wreg = 1;
3327           } else use_wreg = 0;
3328
3329           _G.stackRegSet = _G.sendSet;
3330           _G.sendSet = NULL;
3331     }
3332
3333     /* make the call */
3334     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3335
3336     GpsuedoStkPtr=0;
3337     
3338     /* if we need to assign a result value */
3339     if ((IS_ITEMP(IC_RESULT(ic))
3340           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3341               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3342         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3343
3344       _G.accInUse++;
3345       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3346       _G.accInUse--;
3347
3348       assignResultValue(IC_RESULT(ic), 1);
3349
3350       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3351                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3352                 
3353       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3354     }
3355
3356     if(!stackParms && ic->parmBytes) {
3357       stackParms = ic->parmBytes;
3358     }
3359       
3360     stackParms -= use_wreg;
3361     
3362     if(stackParms>0) {
3363       if(stackParms == 1) {
3364         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3365       } else {
3366         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3367         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3368       }
3369       if(STACK_MODEL_LARGE) {
3370         emitSKPNC;
3371         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3372       }
3373     }
3374
3375 #if 0
3376     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3377 #endif
3378
3379     /* adjust the stack for parameters if required */
3380 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3381
3382 #if 0
3383       /* if register bank was saved then pop them */
3384       if (ic->bankSaved)
3385         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3386
3387       /* if we hade saved some registers then unsave them */
3388       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3389         unsaveRegisters (ic);
3390 #endif
3391 }
3392
3393
3394
3395 /*-----------------------------------------------------------------*/
3396 /* genPcall - generates a call by pointer statement                */
3397 /*            new version, created from genCall - HJD              */
3398 /*-----------------------------------------------------------------*/
3399 static void genPcall (iCode *ic)
3400 {
3401   sym_link *ftype;
3402   int stackParms=0;
3403   symbol *retlbl = newiTempLabel(NULL);
3404   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3405   
3406     FENTRY;
3407
3408     fntype = operandType( IC_LEFT(ic) )->next;
3409
3410     /* if send set is not empty the assign */
3411     if (_G.sendSet) {
3412       iCode *sic;
3413       int psuedoStkPtr=-1; 
3414
3415       /* reverse sendSet if function is not reentrant */
3416       if(!IFFUNC_ISREENT(fntype))
3417         _G.sendSet = reverseSet(_G.sendSet);
3418
3419       stackParms = 0;
3420       
3421       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3422         int size;
3423
3424           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3425           size = AOP_SIZE(IC_LEFT(sic));
3426           stackParms += size;
3427
3428           /* all parameters are passed via stack, since WREG is clobbered
3429            * by the calling sequence */
3430           while (size--) {
3431             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3432             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3433             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3434
3435             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3436             pushw();
3437           }
3438
3439           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3440       }
3441
3442       _G.stackRegSet = _G.sendSet;
3443       _G.sendSet = NULL;
3444     }
3445
3446     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3447
3448     // push return address
3449     // push $ on return stack, then replace with retlbl
3450
3451     /* Thanks to Thorsten Klose for pointing out that the following
3452      * snippet should be interrupt safe */
3453     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3454     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3455
3456     pic16_emitpcodeNULLop(POC_PUSH);
3457
3458     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3459     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3460     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3461     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3462     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3463     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3464
3465
3466     /* restore interrupt control register */
3467     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3468     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3469
3470     /* make the call by writing the pointer into pc */
3471     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3472     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3473
3474     // note: MOVFF to PCL not allowed
3475     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3476     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3477
3478
3479     /* return address is here: (X) */
3480     pic16_emitpLabelFORCE(retlbl->key);
3481
3482     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3483
3484     GpsuedoStkPtr=0;
3485     /* if we need assign a result value */
3486     if ((IS_ITEMP(IC_RESULT(ic))
3487           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3488               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3489         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3490
3491       _G.accInUse++;
3492       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3493       _G.accInUse--;
3494
3495       assignResultValue(IC_RESULT(ic), 1);
3496
3497       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3499                 
3500       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3501     }
3502
3503 //    stackParms -= use_wreg;
3504     
3505     if(stackParms>0) {
3506       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3507       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3508       if(STACK_MODEL_LARGE) {
3509         emitSKPNC;
3510         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3511       }
3512     }
3513 }
3514
3515 /*-----------------------------------------------------------------*/
3516 /* resultRemat - result  is rematerializable                       */
3517 /*-----------------------------------------------------------------*/
3518 static int resultRemat (iCode *ic)
3519 {
3520   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3521   if (SKIP_IC(ic) || ic->op == IFX)
3522     return 0;
3523
3524   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3525     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3526     if (sym->remat && !POINTER_SET(ic)) 
3527       return 1;
3528   }
3529
3530   return 0;
3531 }
3532
3533 #if defined(__BORLANDC__) || defined(_MSC_VER)
3534 #define STRCASECMP stricmp
3535 #else
3536 #define STRCASECMP strcasecmp
3537 #endif
3538
3539 #if 0
3540 /*-----------------------------------------------------------------*/
3541 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3542 /*-----------------------------------------------------------------*/
3543 static bool inExcludeList(char *s)
3544 {
3545   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3546     int i =0;
3547     
3548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3549     if (options.excludeRegs[i] &&
3550     STRCASECMP(options.excludeRegs[i],"none") == 0)
3551         return FALSE ;
3552
3553     for ( i = 0 ; options.excludeRegs[i]; i++) {
3554         if (options.excludeRegs[i] &&
3555         STRCASECMP(s,options.excludeRegs[i]) == 0)
3556             return TRUE;
3557     }
3558     return FALSE ;
3559 }
3560 #endif
3561
3562 /*-----------------------------------------------------------------*/
3563 /* genFunction - generated code for function entry                 */
3564 /*-----------------------------------------------------------------*/
3565 static void genFunction (iCode *ic)
3566 {
3567   symbol *sym;
3568   sym_link *ftype;
3569   
3570     FENTRY;
3571     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3572
3573     pic16_labelOffset += (max_key+4);
3574     max_key=0;
3575     GpsuedoStkPtr=0;
3576     _G.nRegsSaved = 0;
3577         
3578     ftype = operandType(IC_LEFT(ic));
3579     sym = OP_SYMBOL(IC_LEFT(ic));
3580
3581     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3582       /* create an absolute section at the interrupt vector:
3583        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3584       symbol *asym;
3585       char asymname[128];
3586       pBlock *apb;
3587
3588 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3589
3590         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3591           sprintf(asymname, "ivec_%s", sym->name);
3592         else
3593           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3594   
3595         /* when an interrupt is declared as naked, do not emit the special
3596          * wrapper segment at vector address. The user should take care for
3597          * this instead. -- VR */
3598
3599         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3600           asym = newSymbol(asymname, 0);
3601           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3602           pic16_addpBlock( apb );
3603
3604           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3605           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3606           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3607           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3608           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3609                 
3610           /* mark the end of this tiny function */
3611           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3612         } else {
3613           sprintf(asymname, "%s", sym->rname);
3614         }
3615
3616         {
3617           absSym *abSym;
3618
3619             abSym = Safe_calloc(1, sizeof(absSym));
3620             strcpy(abSym->name, asymname);
3621
3622             switch( FUNC_INTNO(sym->type) ) {
3623               case 0: abSym->address = 0x000000; break;
3624               case 1: abSym->address = 0x000008; break;
3625               case 2: abSym->address = 0x000018; break;
3626               
3627               default:
3628 //                fprintf(stderr, "no interrupt number is given\n");
3629                 abSym->address = -1; break;
3630             }
3631
3632             /* relocate interrupt vectors if needed */
3633             if(abSym->address != -1)
3634               abSym->address += pic16_options.ivt_loc;
3635
3636             addSet(&absSymSet, abSym);
3637         }
3638     }
3639
3640     /* create the function header */
3641     pic16_emitcode(";","-----------------------------------------");
3642     pic16_emitcode(";"," function %s",sym->name);
3643     pic16_emitcode(";","-----------------------------------------");
3644
3645     pic16_emitcode("","%s:",sym->rname);
3646     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3647
3648     {
3649       absSym *ab;
3650
3651         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3652           if(!strcmp(ab->name, sym->rname)) {
3653             pic16_pBlockConvert2Absolute(pb);
3654             break;
3655           }
3656         }
3657     }
3658
3659     if(IFFUNC_ISNAKED(ftype)) {
3660       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3661       return;
3662     }
3663         
3664     /* if critical function then turn interrupts off */
3665     if (IFFUNC_ISCRITICAL(ftype)) {
3666       //pic16_emitcode("clr","ea");
3667     }
3668
3669     currFunc = sym;             /* update the currFunc symbol */
3670     _G.fregsUsed = sym->regsUsed;
3671     _G.sregsAlloc = newBitVect(128);
3672     
3673
3674     /* if this is an interrupt service routine then
3675      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3676     if (IFFUNC_ISISR(sym->type)) {
3677         _G.usefastretfie = 1;   /* use shadow registers by default */
3678         
3679         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3680         if(!FUNC_ISSHADOWREGS(sym->type)) {
3681           /* do not save WREG,STATUS,BSR for high priority interrupts
3682            * because they are stored in the hardware shadow registers already */
3683           _G.usefastretfie = 0;
3684           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3685           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3686           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3687         }
3688
3689         /* these should really be optimized somehow, because not all
3690          * interrupt handlers modify them */
3691         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3692         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3693         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3694         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3695         
3696 //        pic16_pBlockConvert2ISR(pb);
3697     }
3698
3699     /* emit code to setup stack frame if user enabled,
3700      * and function is not main() */
3701     
3702 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3703     if(strcmp(sym->name, "main")) {
3704       if(0 
3705         || !options.ommitFramePtr 
3706 //        || sym->regsUsed
3707         || IFFUNC_ARGS(sym->type)
3708         || FUNC_HASSTACKPARM(sym->etype)
3709         ) {
3710         /* setup the stack frame */
3711         if(STACK_MODEL_LARGE)
3712           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3713         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3714
3715         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3716         if(STACK_MODEL_LARGE)
3717           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3718       }
3719     }
3720
3721     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3722           && sym->stack) {
3723
3724       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3725
3726       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3727       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3728       emitSKPC;
3729       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3730     }
3731           
3732     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3733       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3734         _G.useWreg = 0;
3735       else
3736         _G.useWreg = 1;
3737     } else
3738       _G.useWreg = 0;
3739
3740     /* if callee-save to be used for this function
3741      * then save the registers being used in this function */
3742 //    if (IFFUNC_CALLEESAVES(sym->type))
3743     if(strcmp(sym->name, "main")) {
3744       int i;
3745
3746         /* if any registers used */
3747         if (sym->regsUsed) {
3748           /* save the registers used */
3749           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3750           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3751           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3752             if (bitVectBitValue(sym->regsUsed,i)) {
3753               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3754               _G.nRegsSaved++;
3755
3756               if(!pic16_regWithIdx(i)->wasUsed) {
3757                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3758                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3759                 pic16_regWithIdx(i)->wasUsed = 1;
3760               }
3761             }
3762           }
3763           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3764         }
3765     }
3766         
3767     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3768 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3769 }
3770
3771 /*-----------------------------------------------------------------*/
3772 /* genEndFunction - generates epilogue for functions               */
3773 /*-----------------------------------------------------------------*/
3774 static void genEndFunction (iCode *ic)
3775 {
3776   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3777
3778     FENTRY;
3779
3780     if(IFFUNC_ISNAKED(sym->type)) {
3781       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3782       return;
3783     }
3784
3785     _G.stack_lat = 0;
3786
3787     /* add code for ISCRITICAL */
3788     if(IFFUNC_ISCRITICAL(sym->type)) {
3789       /* if critical function, turn on interrupts */
3790       
3791       /* TODO: add code here -- VR */
3792     }
3793     
3794 //    sym->regsUsed = _G.fregsUsed;
3795     
3796     /* now we need to restore the registers */
3797     /* if any registers used */
3798
3799     /* first restore registers that might be used for stack access */
3800     if(_G.sregsAllocSet) {
3801     regs *sr;
3802     
3803       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3804       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3805         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3806       }
3807     }
3808
3809     if (strcmp(sym->name, "main") && sym->regsUsed) {
3810       int i;
3811
3812         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3813         /* restore registers used */
3814         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3815         for ( i = sym->regsUsed->size; i >= 0; i--) {
3816           if (bitVectBitValue(sym->regsUsed,i)) {
3817             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3818             _G.nRegsSaved--;
3819           }
3820         }
3821         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3822     }
3823
3824       
3825
3826     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3827           && sym->stack) {
3828       if (sym->stack == 1) {
3829         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3830         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3831       } else {
3832         // we have to add more than one...
3833         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3834         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3835         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3836         emitSKPNC;
3837         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3838         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3839         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3840       }
3841     }
3842
3843     if(strcmp(sym->name, "main")) {
3844       if(0
3845         || !options.ommitFramePtr
3846 //        || sym->regsUsed
3847         || IFFUNC_ARGS(sym->type)
3848         || FUNC_HASSTACKPARM(sym->etype)
3849         ) {
3850         /* restore stack frame */
3851         if(STACK_MODEL_LARGE)
3852           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3853         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3854       }
3855     }
3856
3857     _G.useWreg = 0;
3858
3859     if (IFFUNC_ISISR(sym->type)) {
3860       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3861       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3862       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3863       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3864
3865       if(!FUNC_ISSHADOWREGS(sym->type)) {
3866         /* do not restore interrupt vector for WREG,STATUS,BSR
3867          * for high priority interrupt, see genFunction */
3868         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3869         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3870         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3871       }
3872 //      _G.interruptvector = 0;         /* sanity check */
3873
3874
3875       /* if debug then send end of function */
3876 /*      if (options.debug && currFunc)  */
3877       if (currFunc) {
3878         debugFile->writeEndFunction (currFunc, ic, 1);
3879       }
3880         
3881       if(_G.usefastretfie)
3882         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3883       else
3884         pic16_emitpcodeNULLop(POC_RETFIE);
3885
3886       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3887       
3888       _G.usefastretfie = 0;
3889       return;
3890     }
3891
3892     if (IFFUNC_ISCRITICAL(sym->type)) {
3893       pic16_emitcode("setb","ea");
3894     }
3895
3896     /* if debug then send end of function */
3897     if (currFunc) {
3898       debugFile->writeEndFunction (currFunc, ic, 1);
3899     }
3900
3901     /* insert code to restore stack frame, if user enabled it
3902      * and function is not main() */
3903          
3904
3905     pic16_emitpcodeNULLop(POC_RETURN);
3906
3907     /* Mark the end of a function */
3908     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3909 }
3910
3911
3912 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3913 {
3914   unsigned long lit=1;
3915   operand *op;
3916
3917     op = IC_LEFT(ic);
3918   
3919     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3920     if(AOP_TYPE(op) == AOP_LIT) {
3921       if(!IS_FLOAT(operandType( op ))) {
3922         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3923       } else {
3924         union {
3925           unsigned long lit_int;
3926           float lit_float;
3927         } info;
3928         
3929         /* take care if literal is a float */
3930         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3931         lit = info.lit_int;
3932       }
3933     }
3934
3935     if(is_LitOp(op)) {
3936       pic16_movLit2f(dest, lit);
3937     } else {
3938       if(dest->type == PO_WREG && (offset == 0)) {
3939         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3940       return;
3941     }
3942     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3943   }
3944 }
3945
3946 /*-----------------------------------------------------------------*/
3947 /* genRet - generate code for return statement                     */
3948 /*-----------------------------------------------------------------*/
3949 static void genRet (iCode *ic)
3950 {
3951   int size;
3952   operand *left;
3953
3954     FENTRY;
3955         /* if we have no return value then
3956          * just generate the "ret" */
3957         
3958         if (!IC_LEFT(ic)) 
3959                 goto jumpret;       
3960     
3961         /* we have something to return then
3962          * move the return value into place */
3963         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3964         size = AOP_SIZE(IC_LEFT(ic));
3965
3966         if(size <= 4) {
3967           if(size>3)
3968             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3969           
3970           if(size>2)
3971             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3972
3973           if(size>1)
3974             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3975           
3976           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3977
3978         } else {
3979                 /* >32-bits, setup stack and FSR0 */
3980                 while (size--) {
3981 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3982 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3983
3984                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3985
3986 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3987                         GpsuedoStkPtr++;
3988                 }
3989                         
3990                 /* setup FSR0 */
3991                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3992                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3993
3994                 if(STACK_MODEL_LARGE) {
3995                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3996                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3997                 } else {
3998                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3999                 }
4000         }
4001                                 
4002 #if 0
4003         /* old code, left here for reference -- VR */    
4004         while (size--) {
4005           char *l ;
4006
4007                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4008                         /* #NOCHANGE */
4009                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4010                         pic16_emitpcomment("push %s",l);
4011                         pushed++;
4012                 } else {
4013                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4014                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4015                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4016                         
4017                         if (strcmp(fReturn[offset],l)) {
4018                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4019                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4020                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4021                                 } else {
4022                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4023                                 }
4024                                 
4025                                 if(size) {
4026                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4027                                 }
4028                                 offset++;
4029                         }
4030                 }
4031         }    
4032
4033         if (pushed) {
4034                 while(pushed) {
4035                         pushed--;
4036                         if (strcmp(fReturn[pushed],"a"))
4037                                 pic16_emitcode("pop",fReturn[pushed]);
4038                         else
4039                                 pic16_emitcode("pop","acc");
4040                 }
4041         }
4042 #endif
4043
4044
4045         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4046     
4047 jumpret:
4048         /* generate a jump to the return label
4049          * if the next is not the return statement */
4050         if (!(ic->next && ic->next->op == LABEL
4051                 && IC_LABEL(ic->next) == returnLabel)) {
4052         
4053                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4054                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4055         }
4056 }
4057
4058 /*-----------------------------------------------------------------*/
4059 /* genLabel - generates a label                                    */
4060 /*-----------------------------------------------------------------*/
4061 static void genLabel (iCode *ic)
4062 {
4063   FENTRY;
4064
4065   /* special case never generate */
4066   if (IC_LABEL(ic) == entryLabel)
4067     return ;
4068
4069   pic16_emitpLabel(IC_LABEL(ic)->key);
4070 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4071 }
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genGoto - generates a goto                                      */
4075 /*-----------------------------------------------------------------*/
4076 //tsd
4077 static void genGoto (iCode *ic)
4078 {
4079   FENTRY;
4080   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4081 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4082 }
4083
4084
4085 /*-----------------------------------------------------------------*/
4086 /* genMultbits :- multiplication of bits                           */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultbits (operand *left, 
4089                          operand *right, 
4090                          operand *result)
4091 {
4092   FENTRY;
4093
4094   if(!pic16_sameRegs(AOP(result),AOP(right)))
4095     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4096
4097   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4098   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4099   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4100
4101 }
4102
4103
4104 /*-----------------------------------------------------------------*/
4105 /* genMultOneByte : 8 bit multiplication & division                */
4106 /*-----------------------------------------------------------------*/
4107 static void genMultOneByte (operand *left,
4108                             operand *right,
4109                             operand *result)
4110 {
4111
4112   FENTRY;
4113   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4114   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4115
4116   /* (if two literals, the value is computed before) */
4117   /* if one literal, literal on the right */
4118   if (AOP_TYPE(left) == AOP_LIT){
4119     operand *t = right;
4120     right = left;
4121     left = t;
4122   }
4123
4124         /* size is already checked in genMult == 1 */
4125 //      size = AOP_SIZE(result);
4126
4127         if (AOP_TYPE(right) == AOP_LIT){
4128                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4129                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4130                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4131                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4132         } else {
4133                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4134                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4135                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4136                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4137         }
4138         
4139         pic16_genMult8X8_8 (left, right,result);
4140 }
4141
4142 /*-----------------------------------------------------------------*/
4143 /* genMultOneWord : 16 bit multiplication                          */
4144 /*-----------------------------------------------------------------*/
4145 static void genMultOneWord (operand *left,
4146                             operand *right,
4147                             operand *result)
4148 {
4149   FENTRY;
4150   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4151   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4152
4153   /* (if two literals, the value is computed before)
4154    * if one literal, literal on the right */
4155   if (AOP_TYPE(left) == AOP_LIT){
4156     operand *t = right;
4157     right = left;
4158     left = t;
4159   }
4160
4161   /* size is checked already == 2 */
4162 //  size = AOP_SIZE(result);
4163
4164   if (AOP_TYPE(right) == AOP_LIT) {
4165     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4166       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4167       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4168       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4169   } else {
4170     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4171       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4172       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4173       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4174   }
4175         
4176   pic16_genMult16X16_16(left, right,result);
4177 }
4178
4179 /*-----------------------------------------------------------------*/
4180 /* genMultOneLong : 32 bit multiplication                          */
4181 /*-----------------------------------------------------------------*/
4182 static void genMultOneLong (operand *left,
4183                             operand *right,
4184                             operand *result)
4185 {
4186   FENTRY;
4187   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4188   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4189
4190   /* (if two literals, the value is computed before)
4191    * if one literal, literal on the right */
4192   if (AOP_TYPE(left) == AOP_LIT){
4193     operand *t = right;
4194     right = left;
4195     left = t;
4196   }
4197
4198   /* size is checked already == 4 */
4199 //  size = AOP_SIZE(result);
4200
4201   if (AOP_TYPE(right) == AOP_LIT) {
4202     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4203         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4204         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4205         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4206   } else {
4207     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4208         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4209         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4210         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4211   }
4212         
4213   pic16_genMult32X32_32(left, right,result);
4214 }
4215
4216
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genMult - generates code for multiplication                     */
4220 /*-----------------------------------------------------------------*/
4221 static void genMult (iCode *ic)
4222 {
4223   operand *left = IC_LEFT(ic);
4224   operand *right = IC_RIGHT(ic);
4225   operand *result= IC_RESULT(ic);   
4226
4227     FENTRY;
4228         /* assign the amsops */
4229         pic16_aopOp (left,ic,FALSE);
4230         pic16_aopOp (right,ic,FALSE);
4231         pic16_aopOp (result,ic,TRUE);
4232
4233         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4234
4235         /* special cases first *
4236         * both are bits */
4237         if (AOP_TYPE(left) == AOP_CRY
4238                 && AOP_TYPE(right)== AOP_CRY) {
4239                 genMultbits(left,right,result);
4240           goto release ;
4241         }
4242
4243         /* if both are of size == 1 */
4244         if(AOP_SIZE(left) == 1
4245                 && AOP_SIZE(right) == 1) {
4246                 genMultOneByte(left,right,result);
4247           goto release ;
4248         }
4249
4250         /* if both are of size == 2 */
4251         if(AOP_SIZE(left) == 2
4252                 && AOP_SIZE(right) == 2) {
4253                 genMultOneWord(left, right, result);
4254           goto release;
4255         }
4256         
4257         /* if both are of size == 4 */
4258         if(AOP_SIZE(left) == 4
4259                 && AOP_SIZE(right) == 4) {
4260                 genMultOneLong(left, right, result);
4261           goto release;
4262         }
4263         
4264         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4265
4266
4267         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4268         /* should have been converted to function call */
4269         assert(0) ;
4270
4271 release :
4272         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4273         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4274         pic16_freeAsmop(result,NULL,ic,TRUE); 
4275 }
4276
4277 /*-----------------------------------------------------------------*/
4278 /* genDivbits :- division of bits                                  */
4279 /*-----------------------------------------------------------------*/
4280 static void genDivbits (operand *left, 
4281                         operand *right, 
4282                         operand *result)
4283 {
4284   char *l;
4285
4286     FENTRY;
4287     /* the result must be bit */    
4288     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4289     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4290
4291     MOVA(l);    
4292
4293     pic16_emitcode("div","ab");
4294     pic16_emitcode("rrc","a");
4295     pic16_aopPut(AOP(result),"c",0);
4296 }
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genDivOneByte : 8 bit division                                  */
4300 /*-----------------------------------------------------------------*/
4301 static void genDivOneByte (operand *left,
4302                            operand *right,
4303                            operand *result)
4304 {
4305   sym_link *opetype = operandType(result);
4306   char *l ;
4307   symbol *lbl ;
4308   int size,offset;
4309
4310         /* result = divident / divisor
4311          * - divident may be a register or a literal,
4312          * - divisor may be a register or a literal,
4313          * so there are 3 cases (literal / literal is optimized
4314          * by the front-end) to handle.
4315          * In addition we must handle signed and unsigned, which
4316          * result in 6 final different cases -- VR */
4317
4318     FENTRY;
4319     
4320     size = AOP_SIZE(result) - 1;
4321     offset = 1;
4322     /* signed or unsigned */
4323     if (SPEC_USIGN(opetype)) {
4324       pCodeOp *pct1,    /* count */
4325                 *pct2,  /* reste */
4326                 *pct3;  /* temp */
4327       symbol *label1, *label2, *label3;;
4328
4329
4330         /* unsigned is easy */
4331
4332         pct1 = pic16_popGetTempReg(1);
4333         pct2 = pic16_popGetTempReg(1);
4334         pct3 = pic16_popGetTempReg(1);
4335         
4336         label1 = newiTempLabel(NULL);
4337         label2 = newiTempLabel(NULL);
4338         label3 = newiTempLabel(NULL);
4339
4340         /* the following algorithm is extracted from divuint.c */
4341
4342         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4343         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4344         
4345         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4346
4347         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4348         
4349         pic16_emitpLabel(label1->key);
4350         
4351         emitCLRC;
4352         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4353
4354
4355         emitCLRC;
4356         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4357         
4358
4359         emitSKPNC;
4360         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4361         
4362         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4363         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4364         
4365         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4366         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4367         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4368         
4369         pic16_emitpLabel( label3->key );
4370         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4371         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4372         
4373         
4374
4375         pic16_emitpLabel(label2->key);
4376         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4377         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4378         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4379         
4380         /* result is in wreg */
4381         if(AOP_TYPE(result) != AOP_ACC)
4382                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4383
4384         pic16_popReleaseTempReg( pct3, 1);
4385         pic16_popReleaseTempReg( pct2, 1);
4386         pic16_popReleaseTempReg( pct1, 1);
4387
4388         return ;
4389     }
4390
4391     /* signed is a little bit more difficult */
4392
4393     /* save the signs of the operands */
4394     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4395     MOVA(l);    
4396     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4397     pic16_emitcode("push","acc"); /* save it on the stack */
4398
4399     /* now sign adjust for both left & right */
4400     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4401     MOVA(l);       
4402     lbl = newiTempLabel(NULL);
4403     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4404     pic16_emitcode("cpl","a");   
4405     pic16_emitcode("inc","a");
4406     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4407     pic16_emitcode("mov","b,a");
4408
4409     /* sign adjust left side */
4410     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4411     MOVA(l);
4412
4413     lbl = newiTempLabel(NULL);
4414     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4415     pic16_emitcode("cpl","a");
4416     pic16_emitcode("inc","a");
4417     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4418
4419     /* now the division */
4420     pic16_emitcode("div","ab");
4421     /* we are interested in the lower order
4422     only */
4423     pic16_emitcode("mov","b,a");
4424     lbl = newiTempLabel(NULL);
4425     pic16_emitcode("pop","acc");   
4426     /* if there was an over flow we don't 
4427     adjust the sign of the result */
4428     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4429     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4430     CLRC;
4431     pic16_emitcode("clr","a");
4432     pic16_emitcode("subb","a,b");
4433     pic16_emitcode("mov","b,a");
4434     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4435
4436     /* now we are done */
4437     pic16_aopPut(AOP(result),"b",0);
4438     if(size > 0){
4439         pic16_emitcode("mov","c,b.7");
4440         pic16_emitcode("subb","a,acc");   
4441     }
4442     while (size--)
4443         pic16_aopPut(AOP(result),"a",offset++);
4444
4445 }
4446
4447 /*-----------------------------------------------------------------*/
4448 /* genDiv - generates code for division                            */
4449 /*-----------------------------------------------------------------*/
4450 static void genDiv (iCode *ic)
4451 {
4452     operand *left = IC_LEFT(ic);
4453     operand *right = IC_RIGHT(ic);
4454     operand *result= IC_RESULT(ic);   
4455
4456
4457         /* Division is a very lengthy algorithm, so it is better
4458          * to call support routines than inlining algorithm.
4459          * Division functions written here just in case someone
4460          * wants to inline and not use the support libraries -- VR */
4461
4462     FENTRY;
4463     
4464     /* assign the amsops */
4465     pic16_aopOp (left,ic,FALSE);
4466     pic16_aopOp (right,ic,FALSE);
4467     pic16_aopOp (result,ic,TRUE);
4468
4469     /* special cases first */
4470     /* both are bits */
4471     if (AOP_TYPE(left) == AOP_CRY &&
4472         AOP_TYPE(right)== AOP_CRY) {
4473         genDivbits(left,right,result);
4474         goto release ;
4475     }
4476
4477     /* if both are of size == 1 */
4478     if (AOP_SIZE(left) == 1 &&
4479         AOP_SIZE(right) == 1 ) {
4480         genDivOneByte(left,right,result);
4481         goto release ;
4482     }
4483
4484     /* should have been converted to function call */
4485     assert(0);
4486 release :
4487     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4488     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489     pic16_freeAsmop(result,NULL,ic,TRUE); 
4490 }
4491
4492 /*-----------------------------------------------------------------*/
4493 /* genModbits :- modulus of bits                                   */
4494 /*-----------------------------------------------------------------*/
4495 static void genModbits (operand *left, 
4496                         operand *right, 
4497                         operand *result)
4498 {
4499   char *l;
4500
4501     FENTRY;  
4502     
4503     werror(W_POSSBUG2, __FILE__, __LINE__);
4504     /* the result must be bit */    
4505     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4506     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4507
4508     MOVA(l);       
4509
4510     pic16_emitcode("div","ab");
4511     pic16_emitcode("mov","a,b");
4512     pic16_emitcode("rrc","a");
4513     pic16_aopPut(AOP(result),"c",0);
4514 }
4515
4516 /*-----------------------------------------------------------------*/
4517 /* genModOneByte : 8 bit modulus                                   */
4518 /*-----------------------------------------------------------------*/
4519 static void genModOneByte (operand *left,
4520                            operand *right,
4521                            operand *result)
4522 {
4523   sym_link *opetype = operandType(result);
4524   char *l ;
4525   symbol *lbl ;
4526
4527     FENTRY;
4528     werror(W_POSSBUG2, __FILE__, __LINE__);
4529
4530     /* signed or unsigned */
4531     if (SPEC_USIGN(opetype)) {
4532         /* unsigned is easy */
4533         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4534         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4535         MOVA(l);    
4536         pic16_emitcode("div","ab");
4537         pic16_aopPut(AOP(result),"b",0);
4538         return ;
4539     }
4540
4541     /* signed is a little bit more difficult */
4542
4543     /* save the signs of the operands */
4544     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4545     MOVA(l);
4546
4547     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4548     pic16_emitcode("push","acc"); /* save it on the stack */
4549
4550     /* now sign adjust for both left & right */
4551     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4552     MOVA(l);
4553
4554     lbl = newiTempLabel(NULL);
4555     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4556     pic16_emitcode("cpl","a");   
4557     pic16_emitcode("inc","a");
4558     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4559     pic16_emitcode("mov","b,a"); 
4560
4561     /* sign adjust left side */
4562     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4563     MOVA(l);
4564
4565     lbl = newiTempLabel(NULL);
4566     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4567     pic16_emitcode("cpl","a");   
4568     pic16_emitcode("inc","a");
4569     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4570
4571     /* now the multiplication */
4572     pic16_emitcode("div","ab");
4573     /* we are interested in the lower order
4574     only */
4575     lbl = newiTempLabel(NULL);
4576     pic16_emitcode("pop","acc");   
4577     /* if there was an over flow we don't 
4578     adjust the sign of the result */
4579     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4580     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4581     CLRC ;
4582     pic16_emitcode("clr","a");
4583     pic16_emitcode("subb","a,b");
4584     pic16_emitcode("mov","b,a");
4585     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4586
4587     /* now we are done */
4588     pic16_aopPut(AOP(result),"b",0);
4589
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genMod - generates code for division                            */
4594 /*-----------------------------------------------------------------*/
4595 static void genMod (iCode *ic)
4596 {
4597   operand *left = IC_LEFT(ic);
4598   operand *right = IC_RIGHT(ic);
4599   operand *result= IC_RESULT(ic);  
4600
4601     FENTRY;
4602     
4603     /* assign the amsops */
4604     pic16_aopOp (left,ic,FALSE);
4605     pic16_aopOp (right,ic,FALSE);
4606     pic16_aopOp (result,ic,TRUE);
4607
4608     /* special cases first */
4609     /* both are bits */
4610     if (AOP_TYPE(left) == AOP_CRY &&
4611         AOP_TYPE(right)== AOP_CRY) {
4612         genModbits(left,right,result);
4613         goto release ;
4614     }
4615
4616     /* if both are of size == 1 */
4617     if (AOP_SIZE(left) == 1 &&
4618         AOP_SIZE(right) == 1 ) {
4619         genModOneByte(left,right,result);
4620         goto release ;
4621     }
4622
4623     /* should have been converted to function call */
4624     assert(0);
4625
4626 release :
4627     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629     pic16_freeAsmop(result,NULL,ic,TRUE); 
4630 }
4631
4632 /*-----------------------------------------------------------------*/
4633 /* genIfxJump :- will create a jump depending on the ifx           */
4634 /*-----------------------------------------------------------------*/
4635 /*
4636   note: May need to add parameter to indicate when a variable is in bit space.
4637 */
4638 static void genIfxJump (iCode *ic, char *jval)
4639 {
4640   FENTRY;
4641   
4642     /* if true label then we jump if condition
4643     supplied is true */
4644     if ( IC_TRUE(ic) ) {
4645
4646         if(strcmp(jval,"a") == 0)
4647           emitSKPZ;
4648         else if (strcmp(jval,"c") == 0)
4649           emitSKPNC;
4650         else {
4651           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4652           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4653         }
4654
4655         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4656         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4657
4658     }
4659     else {
4660         /* false label is present */
4661         if(strcmp(jval,"a") == 0)
4662           emitSKPNZ;
4663         else if (strcmp(jval,"c") == 0)
4664           emitSKPC;
4665         else {
4666           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4667           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4668         }
4669
4670         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4671         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4672
4673     }
4674
4675
4676     /* mark the icode as generated */
4677     ic->generated = 1;
4678 }
4679
4680 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4681 {
4682   FENTRY;
4683   
4684     /* if true label then we jump if condition
4685     supplied is true */
4686     if ( IC_TRUE(ic) ) {
4687       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4688       pic16_emitpcode(POC_BTFSC, jop);
4689
4690       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4691       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4692
4693     } else {
4694       /* false label is present */
4695       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4696       pic16_emitpcode(POC_BTFSS, jop);
4697           
4698       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4699       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4700     }
4701
4702
4703     /* mark the icode as generated */
4704     ic->generated = 1;
4705 }
4706
4707 #if 0
4708 // not needed ATM
4709
4710 /*-----------------------------------------------------------------*/
4711 /* genSkip                                                         */
4712 /*-----------------------------------------------------------------*/
4713 static void genSkip(iCode *ifx,int status_bit)
4714 {
4715   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4716   if(!ifx)
4717     return;
4718
4719   if ( IC_TRUE(ifx) ) {
4720     switch(status_bit) {
4721     case 'z':
4722       emitSKPNZ;
4723       break;
4724
4725     case 'c':
4726       emitSKPNC;
4727       break;
4728
4729     case 'd':
4730       emitSKPDC;
4731       break;
4732
4733     }
4734
4735     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4736     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4737
4738   } else {
4739
4740     switch(status_bit) {
4741
4742     case 'z':
4743       emitSKPZ;
4744       break;
4745
4746     case 'c':
4747       emitSKPC;
4748       break;
4749
4750     case 'd':
4751       emitSKPDC;
4752       break;
4753     }
4754     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4755     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4756
4757   }
4758
4759 }
4760 #endif
4761
4762 /*-----------------------------------------------------------------*/
4763 /* genSkipc                                                        */
4764 /*-----------------------------------------------------------------*/
4765 static void genSkipc(resolvedIfx *rifx)
4766 {
4767   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4768   
4769   if(!rifx)
4770     return;
4771
4772   if(rifx->condition)
4773     emitSKPNC;
4774   else
4775     emitSKPC;
4776
4777   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4778   rifx->generated = 1;
4779 }
4780
4781 #if !(USE_SIMPLE_GENCMP)
4782 /*-----------------------------------------------------------------*/
4783 /* genSkipz2                                                       */
4784 /*-----------------------------------------------------------------*/
4785 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4786 {
4787   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4788   
4789   if(!rifx)
4790     return;
4791
4792   if( (rifx->condition ^ invert_condition) & 1)
4793     emitSKPZ;
4794   else
4795     emitSKPNZ;
4796
4797   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4798   rifx->generated = 1;
4799 }
4800 #endif
4801
4802 #if 0
4803 /*-----------------------------------------------------------------*/
4804 /* genSkipz                                                        */
4805 /*-----------------------------------------------------------------*/
4806 static void genSkipz(iCode *ifx, int condition)
4807 {
4808   if(!ifx)
4809     return;
4810
4811   if(condition)
4812     emitSKPNZ;
4813   else
4814     emitSKPZ;
4815
4816   if ( IC_TRUE(ifx) )
4817     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4818   else
4819     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4820
4821   if ( IC_TRUE(ifx) )
4822     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4823   else
4824     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4825
4826 }
4827 #endif
4828
4829 #if !(USE_SIMPLE_GENCMP)
4830 /*-----------------------------------------------------------------*/
4831 /* genSkipCond                                                     */
4832 /*-----------------------------------------------------------------*/
4833 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4834 {
4835   if(!rifx)
4836     return;
4837
4838   if(rifx->condition)
4839     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4840   else
4841     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4842
4843
4844   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4845   rifx->generated = 1;
4846 }
4847 #endif
4848
4849 #if 0
4850 /*-----------------------------------------------------------------*/
4851 /* genChkZeroes :- greater or less than comparison                 */
4852 /*     For each byte in a literal that is zero, inclusive or the   */
4853 /*     the corresponding byte in the operand with W                */
4854 /*     returns true if any of the bytes are zero                   */
4855 /*-----------------------------------------------------------------*/
4856 static int genChkZeroes(operand *op, int lit,  int size)
4857 {
4858
4859   int i;
4860   int flag =1;
4861
4862   while(size--) {
4863     i = (lit >> (size*8)) & 0xff;
4864
4865     if(i==0) {
4866       if(flag) 
4867         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4868       else
4869         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4870       flag = 0;
4871     }
4872   }
4873
4874   return (flag==0);
4875 }
4876 #endif
4877
4878
4879 /*-----------------------------------------------------------------*/
4880 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4881 /*                  aop (if it's NOT a literal) or from lit (if    */
4882 /*                  aop is a literal)                              */
4883 /*-----------------------------------------------------------------*/
4884 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4885   if (aop->type == AOP_LIT) {
4886     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4887   } else {
4888     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4889   }
4890 }
4891
4892 /*-----------------------------------------------------------------*/
4893 /* genCmp :- greater or less than comparison                       */
4894 /*-----------------------------------------------------------------*/
4895
4896 #if USE_SIMPLE_GENCMP           /* { */
4897
4898 /* genCmp performs a left < right comparison, stores
4899  * the outcome in result (if != NULL) and generates
4900  * control flow code for the ifx (if != NULL).
4901  *
4902  * This version leaves in sequences like
4903  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4904  * which should be optmized by the peephole
4905  * optimizer - RN 2005-01-01 */
4906 static void genCmp (operand *left,operand *right,
4907                     operand *result, iCode *ifx, int sign)
4908 {
4909   resolvedIfx rIfx;
4910   int size;
4911   int offs;
4912   symbol *templbl;
4913   operand *dummy;
4914   unsigned long lit;
4915   unsigned long mask;
4916   int performedLt;
4917
4918   FENTRY;
4919   
4920   assert (left && right);
4921   assert (AOP_SIZE(left) == AOP_SIZE(right));
4922
4923   size = AOP_SIZE(right) - 1;
4924   mask = (0x100UL << (size*8)) - 1;
4925   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4926   performedLt = 1;
4927   templbl = NULL;
4928   lit = 0;
4929   
4930   resolveIfx (&rIfx, ifx);
4931
4932   /* handle for special cases */
4933   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4934       return;
4935
4936   /**********************************************************************
4937    * handle bits - bit compares are promoted to int compares seemingly! *
4938    **********************************************************************/
4939 #if 0
4940   // THIS IS COMPLETELY UNTESTED!
4941   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4942     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4943     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4944     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4945
4946     emitSETC;
4947     // 1 < {0,1} is false --> clear C by skipping the next instruction
4948     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4949     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4950     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4951     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4952     emitCLRC; // only skipped for left=0 && right=1
4953
4954     goto correct_result_in_carry;
4955   } // if
4956 #endif
4957
4958   /*************************************************
4959    * make sure that left is register (or the like) *
4960    *************************************************/
4961   if (!isAOP_REGlike(left)) {
4962     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4963     assert (isAOP_LIT(left));
4964     assert (isAOP_REGlike(right));
4965     // swap left and right
4966     // left < right <==> right > left <==> (right >= left + 1)
4967     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4968
4969     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4970       // MAXVALUE < right? always false
4971       if (performedLt) emitCLRC; else emitSETC;
4972       goto correct_result_in_carry;
4973     } // if
4974
4975     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4976     // that's why we handled it above.
4977     lit++;
4978
4979     dummy = left;
4980     left = right;
4981     right = dummy;
4982
4983     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4984   } else if (isAOP_LIT(right)) {
4985     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4986   } // if
4987
4988   assert (isAOP_REGlike(left)); // left must be register or the like
4989   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4990
4991   /*************************************************
4992    * special cases go here                         *
4993    *************************************************/
4994
4995   if (isAOP_LIT(right)) {
4996     if (!sign) {
4997       // unsigned comparison to a literal
4998       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4999       if (lit == 0) {
5000         // unsigned left < 0? always false
5001         if (performedLt) emitCLRC; else emitSETC;
5002         goto correct_result_in_carry;
5003       }
5004     } else {
5005       // signed comparison to a literal
5006       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5007       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5008         // signed left < 0x80000000? always false
5009         if (performedLt) emitCLRC; else emitSETC;
5010         goto correct_result_in_carry;
5011       } else if (lit == 0) {
5012         // compare left < 0; set CARRY if SIGNBIT(left) is set
5013         if (performedLt) emitSETC; else emitCLRC;
5014         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5015         if (performedLt) emitCLRC; else emitSETC;
5016         goto correct_result_in_carry;
5017       }
5018     } // if (!sign)
5019   } // right is literal
5020
5021   /*************************************************
5022    * perform a general case comparison             *
5023    * make sure we get CARRY==1 <==> left >= right  *
5024    *************************************************/
5025   // compare most significant bytes
5026   //DEBUGpc ("comparing bytes at offset %d", size);
5027   if (!sign) {
5028     // unsigned comparison
5029     mov2w_regOrLit (AOP(right), lit, size);
5030     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5031   } else {
5032     // signed comparison
5033     // (add 2^n to both operands then perform an unsigned comparison)
5034     if (isAOP_LIT(right)) {
5035       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5036       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5037
5038       if (litbyte == 0x80) {
5039         // left >= 0x80 -- always true, but more bytes to come
5040         pic16_mov2w (AOP(left), size);
5041         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5042         emitSETC;
5043       } else {
5044         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5045         pic16_mov2w (AOP(left), size);
5046         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5047         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5048       } // if
5049     } else {
5050       /* using PRODL as a temporary register here */
5051       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5052       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5053       pic16_mov2w (AOP(left), size);
5054       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5055       pic16_emitpcode (POC_MOVWF, pctemp);
5056       pic16_mov2w (AOP(right), size);
5057       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5058       pic16_emitpcode (POC_SUBFW, pctemp);
5059       //pic16_popReleaseTempReg(pctemp, 1);
5060     }
5061   } // if (!sign)
5062
5063   // compare remaining bytes (treat as unsigned case from above)
5064   templbl = newiTempLabel ( NULL );
5065   offs = size;
5066   while (offs--) {
5067     //DEBUGpc ("comparing bytes at offset %d", offs);
5068     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5069     mov2w_regOrLit (AOP(right), lit, offs);
5070     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5071   } // while (offs)
5072   pic16_emitpLabel (templbl->key);
5073   goto result_in_carry;
5074
5075 result_in_carry:
5076   
5077   /****************************************************
5078    * now CARRY contains the result of the comparison: *
5079    * SUBWF sets CARRY iff                             *
5080    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5081    * (F=left, W=right)                                *
5082    ****************************************************/
5083
5084   if (performedLt) {
5085     if (result && AOP_TYPE(result) != AOP_CRY) {
5086       // value will be stored
5087       emitTOGC;
5088     } else {
5089       // value wil only be used in the following genSkipc()
5090       rIfx.condition ^= 1;
5091     }
5092   } // if
5093
5094 correct_result_in_carry:
5095
5096   // assign result to variable (if neccessary)
5097   if (result && AOP_TYPE(result) != AOP_CRY) {
5098     //DEBUGpc ("assign result");
5099     size = AOP_SIZE(result);
5100     while (size--) {
5101       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5102     } // while
5103     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5104   } // if (result)
5105
5106   // perform conditional jump
5107   if (ifx) {
5108     //DEBUGpc ("generate control flow");
5109     genSkipc (&rIfx);
5110     ifx->generated = 1;
5111   } // if
5112 }
5113
5114 #elif 1         /* } */
5115                 /* { */
5116       /* original code */
5117 static void genCmp (operand *left,operand *right,
5118                     operand *result, iCode *ifx, int sign)
5119 {
5120   int size; //, offset = 0 ;
5121   unsigned long lit = 0L,i = 0;
5122   resolvedIfx rFalseIfx;
5123   //  resolvedIfx rTrueIfx;
5124   symbol *truelbl;
5125   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5126 /*
5127   if(ifx) {
5128     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5129     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5130   }
5131 */
5132
5133   FENTRY;
5134   
5135   resolveIfx(&rFalseIfx,ifx);
5136   truelbl  = newiTempLabel(NULL);
5137   size = max(AOP_SIZE(left),AOP_SIZE(right));
5138
5139   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5140
5141 #define _swapp
5142
5143   /* if literal is on the right then swap with left */
5144   if ((AOP_TYPE(right) == AOP_LIT)) {
5145     operand *tmp = right ;
5146     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5147     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5148 #ifdef _swapp
5149
5150     lit = (lit - 1) & mask;
5151     right = left;
5152     left = tmp;
5153     rFalseIfx.condition ^= 1;
5154 #endif
5155
5156   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5157     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5158   }
5159
5160
5161   //if(IC_TRUE(ifx) == NULL)
5162   /* if left & right are bit variables */
5163   if (AOP_TYPE(left) == AOP_CRY &&
5164       AOP_TYPE(right) == AOP_CRY ) {
5165     assert (0 && "bit variables used in genCmp");
5166     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5167     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5168   } else {
5169     /* subtract right from left if at the
5170        end the carry flag is set then we know that
5171        left is greater than right */
5172
5173     symbol *lbl  = newiTempLabel(NULL);
5174
5175 #if 0
5176         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5177                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5178 #endif
5179
5180 #ifndef _swapp
5181     if(AOP_TYPE(right) == AOP_LIT) {
5182
5183       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5184
5185       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5186
5187       /* special cases */
5188
5189       if(lit == 0) {
5190
5191         if(sign != 0) 
5192           genSkipCond(&rFalseIfx,left,size-1,7);
5193         else 
5194           /* no need to compare to 0...*/
5195           /* NOTE: this is a de-generate compare that most certainly 
5196            *       creates some dead code. */
5197           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5198
5199         if(ifx) ifx->generated = 1;
5200         return;
5201
5202       }
5203       size--;
5204
5205       if(size == 0) {
5206         //i = (lit >> (size*8)) & 0xff;
5207         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5208         
5209         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5210
5211         i = ((0-lit) & 0xff);
5212         if(sign) {
5213           if( i == 0x81) { 
5214             /* lit is 0x7f, all signed chars are less than
5215              * this except for 0x7f itself */
5216             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5217             genSkipz2(&rFalseIfx,0);
5218           } else {
5219             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5220             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5221             genSkipc(&rFalseIfx);
5222           }
5223
5224         } else {
5225           if(lit == 1) {
5226             genSkipz2(&rFalseIfx,1);
5227           } else {
5228             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5229             genSkipc(&rFalseIfx);
5230           }
5231         }
5232
5233         if(ifx) ifx->generated = 1;
5234         return;
5235       }
5236
5237       /* chars are out of the way. now do ints and longs */
5238
5239
5240       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5241         
5242       /* special cases */
5243
5244       if(sign) {
5245
5246         if(lit == 0) {
5247           genSkipCond(&rFalseIfx,left,size,7);
5248           if(ifx) ifx->generated = 1;
5249           return;
5250         }
5251
5252         if(lit <0x100) {
5253           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5254
5255           //rFalseIfx.condition ^= 1;
5256           //genSkipCond(&rFalseIfx,left,size,7);
5257           //rFalseIfx.condition ^= 1;
5258
5259           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5260           if(rFalseIfx.condition)
5261             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5262           else
5263             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5264
5265           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5266           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5267           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5268
5269           while(size > 1)
5270             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5271
5272           if(rFalseIfx.condition) {
5273             emitSKPZ;
5274             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5275
5276           } else {
5277             emitSKPNZ;
5278           }
5279
5280           genSkipc(&rFalseIfx);
5281           pic16_emitpLabel(truelbl->key);
5282           if(ifx) ifx->generated = 1;
5283           return;
5284
5285         }
5286
5287         if(size == 1) {
5288
5289           if( (lit & 0xff) == 0) {
5290             /* lower byte is zero */
5291             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5292             i = ((lit >> 8) & 0xff) ^0x80;
5293             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5294             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5295             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5296             genSkipc(&rFalseIfx);
5297
5298
5299             if(ifx) ifx->generated = 1;
5300             return;
5301
5302           }
5303         } else {
5304           /* Special cases for signed longs */
5305           if( (lit & 0xffffff) == 0) {
5306             /* lower byte is zero */
5307             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5308             i = ((lit >> 8*3) & 0xff) ^0x80;
5309             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5310             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5311             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5312             genSkipc(&rFalseIfx);
5313
5314
5315             if(ifx) ifx->generated = 1;
5316             return;
5317
5318           }
5319
5320         }
5321
5322
5323         if(lit & (0x80 << (size*8))) {
5324           /* lit is negative */
5325           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5326
5327           //genSkipCond(&rFalseIfx,left,size,7);
5328
5329           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5330
5331           if(rFalseIfx.condition)
5332             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5333           else
5334             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5335
5336
5337         } else {
5338           /* lit is positive */
5339           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5340           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5341           if(rFalseIfx.condition)
5342             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5343           else
5344             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5345
5346         }
5347
5348         /*
5349           This works, but is only good for ints.
5350           It also requires a "known zero" register.
5351           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5352           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5353           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5354           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5355           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5356           genSkipc(&rFalseIfx);
5357
5358           pic16_emitpLabel(truelbl->key);
5359           if(ifx) ifx->generated = 1;
5360           return;
5361         **/
5362           
5363         /* There are no more special cases, so perform a general compare */
5364   
5365         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5366         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5367
5368         while(size--) {
5369
5370           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5371           emitSKPNZ;
5372           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5373         }
5374         //rFalseIfx.condition ^= 1;
5375         genSkipc(&rFalseIfx);
5376
5377         pic16_emitpLabel(truelbl->key);
5378
5379         if(ifx) ifx->generated = 1;
5380         return;
5381
5382
5383       }
5384
5385
5386       /* sign is out of the way. So now do an unsigned compare */
5387       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5388
5389
5390       /* General case - compare to an unsigned literal on the right.*/
5391
5392       i = (lit >> (size*8)) & 0xff;
5393       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5394       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5395       while(size--) {
5396         i = (lit >> (size*8)) & 0xff;
5397
5398         if(i) {
5399           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5400           emitSKPNZ;
5401           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5402         } else {
5403           /* this byte of the lit is zero, 
5404            *if it's not the last then OR in the variable */
5405           if(size)
5406             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5407         }
5408       }
5409
5410
5411       pic16_emitpLabel(lbl->key);
5412 //      pic16_emitpLabel(truelbl->key);
5413       //if(emitFinalCheck)
5414       genSkipc(&rFalseIfx);
5415       if(sign)
5416         pic16_emitpLabel(truelbl->key);
5417
5418       if(ifx) ifx->generated = 1;
5419       return;
5420
5421
5422     }
5423 #endif  // _swapp
5424
5425     if(AOP_TYPE(left) == AOP_LIT) {
5426       //symbol *lbl = newiTempLabel(NULL);
5427
5428       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5429
5430
5431       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5432
5433       /* Special cases */
5434       if((lit == 0) && (sign == 0)){
5435
5436         size--;
5437         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5438         while(size) 
5439           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5440
5441         genSkipz2(&rFalseIfx,0);
5442         if(ifx) ifx->generated = 1;
5443         return;
5444       }
5445
5446       if(size==1) {
5447         /* Special cases */
5448         lit &= 0xff;
5449         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5450           /* degenerate compare can never be true */
5451           if(rFalseIfx.condition == 0)
5452             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5453
5454           if(ifx) ifx->generated = 1;
5455           return;
5456         }
5457
5458         if(sign) {
5459           /* signed comparisons to a literal byte */
5460
5461           int lp1 = (lit+1) & 0xff;
5462
5463           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5464           switch (lp1) {
5465           case 0:
5466             rFalseIfx.condition ^= 1;
5467             genSkipCond(&rFalseIfx,right,0,7);
5468             break;
5469           case 0x7f:
5470             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5471             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5472             genSkipz2(&rFalseIfx,1);
5473             break;
5474           default:
5475             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5476             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5477             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5478             rFalseIfx.condition ^= 1;
5479             genSkipc(&rFalseIfx);
5480             break;
5481           }
5482         } else {
5483           /* unsigned comparisons to a literal byte */
5484
5485           switch(lit & 0xff ) {
5486           case 0:
5487             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5488             genSkipz2(&rFalseIfx,0);
5489             break;
5490           case 0x7f:
5491             rFalseIfx.condition ^= 1;
5492             genSkipCond(&rFalseIfx,right,0,7);
5493             break;
5494
5495           default:
5496             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5497             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5498             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5499             rFalseIfx.condition ^= 1;
5500             if (AOP_TYPE(result) == AOP_CRY)
5501               genSkipc(&rFalseIfx);
5502             else {
5503               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5504               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5505             }         
5506             break;
5507           }
5508         }
5509
5510         if(ifx) ifx->generated = 1;
5511         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5512                 goto check_carry;
5513         return;
5514
5515       } else {
5516
5517         /* Size is greater than 1 */
5518
5519         if(sign) {
5520           int lp1 = lit+1;
5521
5522           size--;
5523
5524           if(lp1 == 0) {
5525             /* this means lit = 0xffffffff, or -1 */
5526
5527
5528             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5529             rFalseIfx.condition ^= 1;
5530             genSkipCond(&rFalseIfx,right,size,7);
5531             if(ifx) ifx->generated = 1;
5532
5533             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5534               goto check_carry;
5535
5536             return;
5537           }
5538
5539           if(lit == 0) {
5540             int s = size;
5541
5542             if(rFalseIfx.condition) {
5543               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5544               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5545             }
5546
5547             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5548             while(size--)
5549               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5550
5551
5552             emitSKPZ;
5553             if(rFalseIfx.condition) {
5554               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5555               pic16_emitpLabel(truelbl->key);
5556             }else {
5557               rFalseIfx.condition ^= 1;
5558               genSkipCond(&rFalseIfx,right,s,7);
5559             }
5560
5561             if(ifx) ifx->generated = 1;
5562
5563             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5564               goto check_carry;
5565
5566             return;
5567           }
5568
5569           if((size == 1) &&  (0 == (lp1&0xff))) {
5570             /* lower byte of signed word is zero */
5571             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5572             i = ((lp1 >> 8) & 0xff) ^0x80;
5573             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5574             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5575             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5576
5577             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5578               emitTOGC;
5579               if(ifx) ifx->generated = 1;
5580               goto check_carry;
5581             } else {
5582               rFalseIfx.condition ^= 1;
5583               genSkipc(&rFalseIfx);
5584               if(ifx) ifx->generated = 1;
5585             }
5586
5587             return;
5588           }
5589
5590           if(lit & (0x80 << (size*8))) {
5591             /* Lit is less than zero */
5592             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5593             //rFalseIfx.condition ^= 1;
5594             //genSkipCond(&rFalseIfx,left,size,7);
5595             //rFalseIfx.condition ^= 1;
5596             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5597             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5598
5599             if(rFalseIfx.condition)
5600               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5601             else
5602               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5603
5604
5605           } else {
5606             /* Lit is greater than or equal to zero */
5607             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5608             //rFalseIfx.condition ^= 1;
5609             //genSkipCond(&rFalseIfx,right,size,7);
5610             //rFalseIfx.condition ^= 1;
5611
5612             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5613             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5614
5615             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5616             if(rFalseIfx.condition)
5617               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5618             else
5619               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5620
5621           }
5622
5623           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5624           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5625
5626           while(size--) {
5627
5628             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5629             emitSKPNZ;
5630             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5631           }
5632           rFalseIfx.condition ^= 1;
5633           //rFalseIfx.condition = 1;
5634           genSkipc(&rFalseIfx);
5635
5636           pic16_emitpLabel(truelbl->key);
5637
5638           if(ifx) ifx->generated = 1;
5639
5640
5641           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5642             goto check_carry;
5643
5644           return;
5645           // end of if (sign)
5646         } else {
5647
5648           /* compare word or long to an unsigned literal on the right.*/
5649
5650
5651           size--;
5652           if(lit < 0xff) {
5653             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5654             switch (lit) {
5655             case 0:
5656               break; /* handled above */
5657 /*
5658             case 0xff:
5659               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5660               while(size--)
5661                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5662               genSkipz2(&rFalseIfx,0);
5663               break;
5664 */
5665             default:
5666               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5667               while(--size)
5668                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5669
5670               emitSKPZ;
5671               if(rFalseIfx.condition)
5672                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5673               else
5674                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5675
5676
5677               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5678               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5679
5680               rFalseIfx.condition ^= 1;
5681               genSkipc(&rFalseIfx);
5682             }
5683
5684             pic16_emitpLabel(truelbl->key);
5685
5686             if(ifx) ifx->generated = 1;
5687
5688             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5689               goto check_carry;
5690
5691             return;
5692           }
5693
5694
5695           lit++;
5696           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5697           i = (lit >> (size*8)) & 0xff;
5698
5699           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5700           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701
5702           while(size--) {
5703             i = (lit >> (size*8)) & 0xff;
5704
5705             if(i) {
5706               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5707               emitSKPNZ;
5708               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5709             } else {
5710               /* this byte of the lit is zero, 
5711                * if it's not the last then OR in the variable */
5712               if(size)
5713                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5714             }
5715           }
5716
5717
5718           pic16_emitpLabel(lbl->key);
5719
5720           rFalseIfx.condition ^= 1;
5721
5722           genSkipc(&rFalseIfx);
5723         }
5724
5725         if(sign)
5726           pic16_emitpLabel(truelbl->key);
5727         if(ifx) ifx->generated = 1;
5728
5729             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5730               goto check_carry;
5731
5732         return;
5733       }
5734     }
5735     /* Compare two variables */
5736
5737     DEBUGpic16_emitcode(";sign","%d",sign);
5738
5739     size--;
5740     if(sign) {
5741       /* Sigh. thus sucks... */
5742       if(size) {
5743         pCodeOp *pctemp;
5744         
5745         pctemp = pic16_popGetTempReg(1);
5746         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5747         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5748         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5749         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5750         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5751         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5752         pic16_popReleaseTempReg(pctemp, 1);
5753       } else {
5754         /* Signed char comparison */
5755         /* Special thanks to Nikolai Golovchenko for this snippet */
5756         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5757         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5758         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5759         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5760         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5761         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5762
5763         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5764         genSkipc(&rFalseIfx);
5765           
5766         if(ifx) ifx->generated = 1;
5767
5768             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769               goto check_carry;
5770
5771         return;
5772       }
5773
5774     } else {
5775
5776       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5777       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5778     }
5779
5780
5781     /* The rest of the bytes of a multi-byte compare */
5782     while (size) {
5783
5784       emitSKPZ;
5785       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5786       size--;
5787
5788       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5789       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5790
5791
5792     }
5793
5794     pic16_emitpLabel(lbl->key);
5795
5796     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5797     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5798         (AOP_TYPE(result) == AOP_REG)) {
5799       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5800       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5801     } else {
5802       genSkipc(&rFalseIfx);
5803     }         
5804     //genSkipc(&rFalseIfx);
5805     if(ifx) ifx->generated = 1;
5806
5807
5808             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5809               goto check_carry;
5810
5811     return;
5812
5813   }
5814
5815 check_carry:
5816   if ((AOP_TYPE(result) != AOP_CRY) 
5817         && AOP_SIZE(result)) {
5818     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5819
5820     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5821
5822     pic16_outBitC(result);
5823   } else {
5824     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5825     /* if the result is used in the next
5826        ifx conditional branch then generate
5827        code a little differently */
5828     if (ifx )
5829       genIfxJump (ifx,"c");
5830     else
5831       pic16_outBitC(result);
5832     /* leave the result in acc */
5833   }
5834
5835 }
5836
5837 #elif 0 /* VR version of genCmp() */    /* } else { */
5838
5839 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5840 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5841         operand *result, int offset, int invert_op)
5842 {
5843   /* add code here */
5844   
5845   /* check condition, > or < ?? */
5846   if(rIfx->condition != 0)invert_op ^= 1;
5847   
5848   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5849
5850   if(!ifx)invert_op ^= 1;
5851
5852   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5853       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5854   
5855   /* do selection */
5856   if(!invert_op)return POC_CPFSGT;
5857   else return POC_CPFSLT;
5858 }
5859
5860 static int compareAopfirstpass=1;
5861
5862 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5863             operand *oper, int offset, operand *result,
5864             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5865             symbol *tlbl)
5866 {
5867   int op;
5868   symbol *truelbl;
5869
5870   /* invert if there is a result to be loaded, in order to fit,
5871    * SETC/CLRC sequence */
5872   if(AOP_SIZE(result))invert_op ^= 1;
5873
5874 //  if(sign && !offset)invert_op ^= 1;
5875   
5876 //  if(sign)invert_op ^= 1;
5877   
5878   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5879
5880   if(AOP_SIZE(result) && compareAopfirstpass) {
5881     if(!ifx) {
5882       if(pcop2)
5883         pic16_emitpcode(POC_SETF, pcop2);
5884       else
5885         emitSETC;
5886     } else {
5887       if(pcop2)
5888         pic16_emitpcode(POC_CLRF, pcop2);
5889       else
5890         emitCLRC;
5891     }
5892   }
5893
5894   compareAopfirstpass = 0;
5895
5896       /* there is a bug when comparing operands with size > 1,
5897        * because higher bytes can be equal and test should be performed
5898        * to the next lower byte, current algorithm, considers operands
5899        * inequal in these cases! -- VR 20041107 */
5900
5901     
5902   if(pcop)
5903     pic16_emitpcode(op, pcop);
5904   else
5905     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5906
5907
5908   if((!sign || !offset) && AOP_SIZE(result)) {
5909     if(!ifx) {
5910       if(pcop2)
5911         pic16_emitpcode(POC_CLRF, pcop2);
5912         else
5913         emitCLRC;
5914     } else {
5915       if(pcop2)
5916         pic16_emitpcode(POC_SETF, pcop2);
5917       else
5918         emitSETC;
5919     }
5920     
5921     /* don't emit final branch (offset == 0) */
5922     if(offset) {
5923
5924       if(pcop2)
5925         pic16_emitpcode(POC_RRCF, pcop2);
5926
5927       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5928     }
5929   } else {
5930     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5931       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5932             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5933
5934       truelbl = newiTempLabel( NULL );
5935       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5936       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5937         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5938       else
5939         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5940       pic16_emitpLabel(truelbl->key);
5941     } else {
5942       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5943     }
5944   }
5945 }
5946
5947 static void genCmp (operand *left, operand *right,
5948                     operand *result, iCode *ifx, int sign)
5949 {
5950   int size, cmpop=1;
5951   long lit = 0L;
5952   resolvedIfx rFalseIfx;
5953   symbol *falselbl, *tlbl;
5954
5955     FENTRY;
5956     
5957     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5958
5959     resolveIfx(&rFalseIfx, ifx);
5960     size = max(AOP_SIZE(left), AOP_SIZE(right));
5961     
5962     /* if left & right are bit variables */
5963     if(AOP_TYPE(left) == AOP_CRY
5964       && AOP_TYPE(right) == AOP_CRY ) {
5965
5966         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5967         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5968         
5969         werror(W_POSSBUG2, __FILE__, __LINE__);
5970         exit(-1);
5971     }
5972     
5973     /* if literal is on the right then swap with left */
5974     if((AOP_TYPE(right) == AOP_LIT)) {
5975       operand *tmp = right ;
5976 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5977
5978         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5979
5980 //      lit = (lit - 1) & mask;
5981         right = left;
5982         left = tmp;
5983         rFalseIfx.condition ^= 1;               /* reverse compare */
5984     } else
5985     if ((AOP_TYPE(left) == AOP_LIT)) {
5986       /* float compares are handled by support functions */
5987       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5988     }
5989
5990     /* actual comparing algorithm */
5991 //    size = AOP_SIZE( right );
5992
5993     falselbl = newiTempLabel( NULL );
5994     if(AOP_TYPE(left) == AOP_LIT) {
5995       /* compare to literal */
5996       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5997       
5998       if(sign) {
5999         pCodeOp *pct, *pct2;
6000         symbol *tlbl1;
6001
6002         /* signed compare */
6003         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6004
6005         /* using PRODL:PRODH as a temporary register here */
6006         pct = pic16_popCopyReg(&pic16_pc_prodl);
6007         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6008         tlbl = newiTempLabel( NULL );
6009         
6010         /* first compare signs:
6011          *  a. if both are positive, compare just like unsigned
6012          *  b. if both are negative, invert cmpop, compare just like unsigned
6013          *  c. if different signs, determine the result directly */
6014
6015         size--;
6016
6017 #if 1
6018         /* { */
6019         tlbl1 = newiTempLabel( NULL );
6020 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6021
6022         if(lit > 0) {
6023
6024           /* literal is zero or positive:
6025            *  a. if carry is zero, too, continue compare,
6026            *  b. if carry is set, then continue depending on cmpop ^ condition:
6027            *    1. '<' return false (literal < variable),
6028            *    2. '>' return true (literal > variable) */
6029 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6030           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6031           
6032           
6033           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6034           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6035         } else 
6036         if(lit < 0) {
6037           
6038           /* literal is negative:
6039            *  a. if carry is set, too, continue compare,
6040            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6041            *    1. '<' return true (literal < variable),
6042            *    2. '>' return false (literal > variable) */
6043 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6044           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6045           
6046           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6047           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6048         }
6049 #if 1
6050         else {
6051           /* lit == 0 */
6052           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6053           
6054           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6055           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6056         }
6057 #endif
6058         
6059         
6060         pic16_emitpLabel( tlbl1->key );
6061 #endif  /* } */
6062
6063         compareAopfirstpass=1;
6064 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6065 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6066 //        pic16_emitpcode(POC_MOVWF, pct);
6067
6068 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6069         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6070 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6071         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6072
6073         /* generic case */        
6074           while( size-- ) {
6075 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6076 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6077 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6078 //            pic16_emitpcode(POC_MOVWF, pct);
6079
6080 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6081             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6082             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6083 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6084 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6085           }
6086         
6087         if(ifx)ifx->generated = 1;
6088
6089         if(AOP_SIZE(result)) {
6090           pic16_emitpLabel(tlbl->key);
6091           pic16_emitpLabel(falselbl->key);
6092           pic16_outBitOp( result, pct2 );
6093         } else {
6094           pic16_emitpLabel(tlbl->key);
6095         }
6096       } else {
6097
6098         /* unsigned compare */      
6099         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6100     
6101         compareAopfirstpass=1;
6102         while(size--) {
6103           
6104           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6105           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6106
6107         }
6108         if(ifx)ifx->generated = 1;
6109
6110         if(AOP_SIZE(result)) {
6111           pic16_emitpLabel(falselbl->key);
6112           pic16_outBitC( result );
6113         }
6114
6115       }
6116     } else {
6117       /* compare registers */
6118       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6119
6120
6121       if(sign) {
6122         pCodeOp *pct, *pct2;
6123         
6124         /* signed compare */
6125         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6126
6127         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6128         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6129         tlbl = newiTempLabel( NULL );
6130         
6131         compareAopfirstpass=1;
6132
6133         size--;
6134         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6135 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6136         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6137         pic16_emitpcode(POC_MOVWF, pct);
6138
6139         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6140 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6141         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6142
6143         /* WREG already holds left + 0x80 */
6144         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6145         
6146         while( size-- ) {
6147           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6148 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6149           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6150           pic16_emitpcode(POC_MOVWF, pct);
6151                 
6152           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6153 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6155
6156           /* WREG already holds left + 0x80 */
6157           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6158 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6159         }
6160         
6161         if(ifx)ifx->generated = 1;
6162
6163         if(AOP_SIZE(result)) {
6164           pic16_emitpLabel(tlbl->key);
6165           pic16_emitpLabel(falselbl->key);
6166           pic16_outBitOp( result, pct2 );
6167         } else {
6168           pic16_emitpLabel(tlbl->key);
6169         }
6170
6171       } else {
6172         /* unsigned compare */      
6173         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6174
6175         compareAopfirstpass=1;
6176         while(size--) {
6177           
6178           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6179           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6180
6181         }
6182
6183         if(ifx)ifx->generated = 1;
6184         if(AOP_SIZE(result)) {
6185
6186           pic16_emitpLabel(falselbl->key);
6187           pic16_outBitC( result );
6188         }
6189
6190       }
6191     }
6192 }
6193
6194 #endif  /* } */
6195
6196
6197
6198 /*-----------------------------------------------------------------*/
6199 /* genCmpGt :- greater than comparison                             */
6200 /*-----------------------------------------------------------------*/
6201 static void genCmpGt (iCode *ic, iCode *ifx)
6202 {
6203   operand *left, *right, *result;
6204   sym_link *letype , *retype;
6205   int sign ;
6206
6207     FENTRY;
6208     
6209     left = IC_LEFT(ic);
6210     right= IC_RIGHT(ic);
6211     result = IC_RESULT(ic);
6212
6213     letype = getSpec(operandType(left));
6214     retype =getSpec(operandType(right));
6215     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6216     /* assign the amsops */
6217     pic16_aopOp (left,ic,FALSE);
6218     pic16_aopOp (right,ic,FALSE);
6219     pic16_aopOp (result,ic,TRUE);
6220
6221     genCmp(right, left, result, ifx, sign);
6222
6223     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6224     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6225     pic16_freeAsmop(result,NULL,ic,TRUE); 
6226 }
6227
6228 /*-----------------------------------------------------------------*/
6229 /* genCmpLt - less than comparisons                                */
6230 /*-----------------------------------------------------------------*/
6231 static void genCmpLt (iCode *ic, iCode *ifx)
6232 {
6233   operand *left, *right, *result;
6234   sym_link *letype , *retype;
6235   int sign ;
6236
6237     FENTRY;
6238
6239     left = IC_LEFT(ic);
6240     right= IC_RIGHT(ic);
6241     result = IC_RESULT(ic);
6242
6243     letype = getSpec(operandType(left));
6244     retype =getSpec(operandType(right));
6245     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6246
6247     /* assign the amsops */
6248     pic16_aopOp (left,ic,FALSE);
6249     pic16_aopOp (right,ic,FALSE);
6250     pic16_aopOp (result,ic,TRUE);
6251
6252     genCmp(left, right, result, ifx, sign);
6253
6254     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6255     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6256     pic16_freeAsmop(result,NULL,ic,TRUE); 
6257 }
6258
6259 #if 0
6260 // not needed ATM
6261 // FIXME reenable literal optimisation when the pic16 port is stable
6262
6263 /*-----------------------------------------------------------------*/
6264 /* genc16bit2lit - compare a 16 bit value to a literal             */
6265 /*-----------------------------------------------------------------*/
6266 static void genc16bit2lit(operand *op, int lit, int offset)
6267 {
6268   int i;
6269
6270   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6271   if( (lit&0xff) == 0) 
6272     i=1;
6273   else
6274     i=0;
6275
6276   switch( BYTEofLONG(lit,i)) { 
6277   case 0:
6278     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6279     break;
6280   case 1:
6281     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6282     break;
6283   case 0xff:
6284     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6285     break;
6286   default:
6287     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6288     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6289   }
6290
6291   i ^= 1;
6292
6293   switch( BYTEofLONG(lit,i)) { 
6294   case 0:
6295     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6296     break;
6297   case 1:
6298     emitSKPNZ;
6299     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6300     break;
6301   case 0xff:
6302     emitSKPNZ;
6303     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6304     break;
6305   default:
6306     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6307     emitSKPNZ;
6308     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6309
6310   }
6311
6312 }
6313 #endif
6314
6315 #if 0
6316 // not needed ATM
6317 /*-----------------------------------------------------------------*/
6318 /* gencjneshort - compare and jump if not equal                    */
6319 /*-----------------------------------------------------------------*/
6320 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6321 {
6322   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6323   int offset = 0;
6324   int res_offset = 0;  /* the result may be a different size then left or right */
6325   int res_size = AOP_SIZE(result);
6326   resolvedIfx rIfx;
6327   symbol *lbl, *lbl_done;
6328
6329   unsigned long lit = 0L;
6330   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6331
6332   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6333   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6334   if(result)
6335     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6336   resolveIfx(&rIfx,ifx);
6337   lbl =  newiTempLabel(NULL);
6338   lbl_done =  newiTempLabel(NULL);
6339
6340
6341   /* if the left side is a literal or 
6342      if the right is in a pointer register and left 
6343      is not */
6344   if ((AOP_TYPE(left) == AOP_LIT) || 
6345       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6346     operand *t = right;
6347     right = left;
6348     left = t;
6349   }
6350   if(AOP_TYPE(right) == AOP_LIT)
6351     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6352
6353   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6354     preserve_result = 1;
6355
6356   if(result && !preserve_result)
6357     {
6358       int i;
6359       for(i = 0; i < AOP_SIZE(result); i++)
6360         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6361     }
6362
6363
6364   /* if the right side is a literal then anything goes */
6365   if (AOP_TYPE(right) == AOP_LIT &&
6366       AOP_TYPE(left) != AOP_DIR ) {
6367     switch(size) {
6368     case 2:
6369       genc16bit2lit(left, lit, 0);
6370       emitSKPZ;
6371       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6372       break;
6373     default:
6374       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6375       while (size--) {
6376         if(lit & 0xff) {
6377           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6378           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6379         } else {
6380           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6381         }
6382
6383         emitSKPZ;
6384         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6385         offset++;
6386         if(res_offset < res_size-1)
6387           res_offset++;
6388         lit >>= 8;
6389       }
6390       break;
6391     }
6392   }
6393
6394   /* if the right side is in a register or in direct space or
6395      if the left is a pointer register & right is not */    
6396   else if (AOP_TYPE(right) == AOP_REG ||
6397            AOP_TYPE(right) == AOP_DIR || 
6398            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6399            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6400     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6401     int lbl_key = lbl->key;
6402
6403     if(result) {
6404       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6405       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6406     }else {
6407       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6408       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6409               __FUNCTION__,__LINE__);
6410       return;
6411     }
6412    
6413 /*     switch(size) { */
6414 /*     case 2: */
6415 /*       genc16bit2lit(left, lit, 0); */
6416 /*       emitSKPNZ; */
6417 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6418 /*       break; */
6419 /*     default: */
6420     while (size--) {
6421       int emit_skip=1;
6422       if((AOP_TYPE(left) == AOP_DIR) && 
6423          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6424
6425         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6426         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6427
6428       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6429             
6430         switch (lit & 0xff) {
6431         case 0:
6432           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6433           break;
6434         case 1:
6435           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6436           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6437           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6438           emit_skip=0;
6439           break;
6440         case 0xff:
6441           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6442           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6443           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6444           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6445           emit_skip=0;
6446           break;
6447         default:
6448           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6450         }
6451         lit >>= 8;
6452
6453       } else {
6454         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6455       }
6456       if(emit_skip) {
6457         if(AOP_TYPE(result) == AOP_CRY) {
6458           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6459           if(rIfx.condition)
6460             emitSKPNZ;
6461           else
6462             emitSKPZ;
6463           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6464         } else {
6465           /* fix me. probably need to check result size too */
6466           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6467           if(rIfx.condition)
6468             emitSKPZ;
6469           else
6470             emitSKPNZ;
6471           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6472           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6473         }
6474         if(ifx)
6475           ifx->generated=1;
6476       }
6477       emit_skip++;
6478       offset++;
6479       if(res_offset < res_size-1)
6480         res_offset++;
6481     }
6482 /*       break; */
6483 /*     } */
6484   } else if(AOP_TYPE(right) == AOP_REG &&
6485             AOP_TYPE(left) != AOP_DIR){
6486
6487     while(size--) {
6488       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6489       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6490       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6491       if(rIfx.condition)
6492         emitSKPNZ;
6493       else
6494         emitSKPZ;
6495       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6496       offset++;
6497       if(res_offset < res_size-1)
6498         res_offset++;
6499     }
6500       
6501   }else{
6502     /* right is a pointer reg need both a & b */
6503     while(size--) {
6504       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6505       if(strcmp(l,"b"))
6506         pic16_emitcode("mov","b,%s",l);
6507       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6508       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6509       offset++;
6510     }
6511   }
6512
6513   if(result && preserve_result)
6514     {
6515       int i;
6516       for(i = 0; i < AOP_SIZE(result); i++)
6517         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6518     }
6519
6520   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6521
6522   if(result && preserve_result)
6523     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6524
6525   if(!rIfx.condition)
6526     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6527
6528   pic16_emitpLabel(lbl->key);
6529
6530   if(result && preserve_result)
6531     {
6532       int i;
6533       for(i = 0; i < AOP_SIZE(result); i++)
6534         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6535
6536       pic16_emitpLabel(lbl_done->key);
6537    }
6538
6539   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6540
6541   if(ifx)
6542     ifx->generated = 1;
6543 }
6544 #endif
6545
6546 #if 0
6547 /*-----------------------------------------------------------------*/
6548 /* gencjne - compare and jump if not equal                         */
6549 /*-----------------------------------------------------------------*/
6550 static void gencjne(operand *left, operand *right, iCode *ifx)
6551 {
6552     symbol *tlbl  = newiTempLabel(NULL);
6553
6554     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6555     gencjneshort(left, right, lbl);
6556
6557     pic16_emitcode("mov","a,%s",one);
6558     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6559     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6560     pic16_emitcode("clr","a");
6561     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6562
6563     pic16_emitpLabel(lbl->key);
6564     pic16_emitpLabel(tlbl->key);
6565
6566 }
6567 #endif
6568
6569
6570 /*-----------------------------------------------------------------*/
6571 /* is_LitOp - check if operand has to be treated as literal        */
6572 /*-----------------------------------------------------------------*/
6573 static bool is_LitOp(operand *op)
6574 {
6575   return ((AOP_TYPE(op) == AOP_LIT)
6576       || ( (AOP_TYPE(op) == AOP_PCODE)
6577           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6578               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6579 }
6580
6581 /*-----------------------------------------------------------------*/
6582 /* is_LitAOp - check if operand has to be treated as literal        */
6583 /*-----------------------------------------------------------------*/
6584 static bool is_LitAOp(asmop *aop)
6585 {
6586   return ((aop->type == AOP_LIT)
6587       || ( (aop->type == AOP_PCODE)
6588           && ( (aop->aopu.pcop->type == PO_LITERAL)
6589               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6590 }
6591
6592
6593
6594 /*-----------------------------------------------------------------*/
6595 /* genCmpEq - generates code for equal to                          */
6596 /*-----------------------------------------------------------------*/
6597 static void genCmpEq (iCode *ic, iCode *ifx)
6598 {
6599   operand *left, *right, *result;
6600   symbol *falselbl = newiTempLabel(NULL);
6601   symbol *donelbl = newiTempLabel(NULL);
6602
6603   int preserve_result = 0;
6604   int generate_result = 0;
6605   int i=0;
6606   unsigned long lit = -1;
6607
6608   FENTRY;
6609   
6610   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6611   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6612   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6613  
6614   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6615
6616   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6617     {
6618       werror(W_POSSBUG2, __FILE__, __LINE__);
6619       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6620       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6621       goto release;
6622     }
6623
6624   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6625     {
6626       operand *tmp = right ;
6627       right = left;
6628       left = tmp;
6629     }
6630
6631   if (AOP_TYPE(right) == AOP_LIT) {
6632     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6633   }
6634
6635   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6636     preserve_result = 1;
6637
6638   if(result && AOP_SIZE(result))
6639     generate_result = 1;
6640
6641   if(generate_result && !preserve_result)
6642     {
6643       for(i = 0; i < AOP_SIZE(result); i++)
6644         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6645     }
6646
6647   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6648   for(i=0; i < AOP_SIZE(left); i++)
6649     {
6650       if(AOP_TYPE(left) != AOP_ACC)
6651         {
6652           if(is_LitOp(left))
6653             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6654           else
6655             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6656         }
6657       if(is_LitOp(right)) {
6658         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6659           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6660         }
6661       } else
6662         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6663
6664       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6665     }
6666
6667   // result == true
6668
6669   if(generate_result && preserve_result)
6670     {
6671       for(i = 0; i < AOP_SIZE(result); i++)
6672         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6673     }
6674
6675   if(generate_result)
6676     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6677
6678   if(generate_result && preserve_result)
6679     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6680
6681   if(ifx && IC_TRUE(ifx))
6682     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6683
6684   if(ifx && IC_FALSE(ifx))
6685     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6686
6687   pic16_emitpLabel(falselbl->key);
6688
6689   // result == false
6690
6691   if(ifx && IC_FALSE(ifx))
6692     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6693
6694   if(generate_result && preserve_result)
6695     {
6696       for(i = 0; i < AOP_SIZE(result); i++)
6697         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6698     }
6699
6700   pic16_emitpLabel(donelbl->key);
6701
6702   if(ifx)
6703     ifx->generated = 1;
6704
6705 release:
6706   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6707   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6708   pic16_freeAsmop(result,NULL,ic,TRUE);
6709
6710 }
6711
6712
6713 #if 0
6714 // old version kept for reference
6715
6716 /*-----------------------------------------------------------------*/
6717 /* genCmpEq - generates code for equal to                          */
6718 /*-----------------------------------------------------------------*/
6719 static void genCmpEq (iCode *ic, iCode *ifx)
6720 {
6721     operand *left, *right, *result;
6722     unsigned long lit = 0L;
6723     int size,offset=0;
6724     symbol *falselbl  = newiTempLabel(NULL);
6725
6726
6727     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6728
6729     if(ifx)
6730       DEBUGpic16_emitcode ("; ifx is non-null","");
6731     else
6732       DEBUGpic16_emitcode ("; ifx is null","");
6733
6734     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6735     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6736     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6737
6738     size = max(AOP_SIZE(left),AOP_SIZE(right));
6739
6740     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6741
6742     /* if literal, literal on the right or 
6743     if the right is in a pointer register and left 
6744     is not */
6745     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6746         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6747       operand *tmp = right ;
6748       right = left;
6749       left = tmp;
6750     }
6751
6752
6753     if(ifx && !AOP_SIZE(result)){
6754         symbol *tlbl;
6755         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6756         /* if they are both bit variables */
6757         if (AOP_TYPE(left) == AOP_CRY &&
6758             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6759                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6760             if(AOP_TYPE(right) == AOP_LIT){
6761                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6762                 if(lit == 0L){
6763                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6764                     pic16_emitcode("cpl","c");
6765                 } else if(lit == 1L) {
6766                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6767                 } else {
6768                     pic16_emitcode("clr","c");
6769                 }
6770                 /* AOP_TYPE(right) == AOP_CRY */
6771             } else {
6772                 symbol *lbl = newiTempLabel(NULL);
6773                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6774                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6775                 pic16_emitcode("cpl","c");
6776                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6777             }
6778             /* if true label then we jump if condition
6779             supplied is true */
6780             tlbl = newiTempLabel(NULL);
6781             if ( IC_TRUE(ifx) ) {
6782                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6783                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6784             } else {
6785                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6786                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6787             }
6788             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6789
6790                 {
6791                 /* left and right are both bit variables, result is carry */
6792                         resolvedIfx rIfx;
6793               
6794                         resolveIfx(&rIfx,ifx);
6795
6796                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6797                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6798                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6799                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6800                         genSkipz2(&rIfx,0);
6801                 }
6802         } else {
6803
6804                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6805
6806                         /* They're not both bit variables. Is the right a literal? */
6807                         if(AOP_TYPE(right) == AOP_LIT) {
6808                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6809             
6810                         switch(size) {
6811
6812                                 case 1:
6813                                         switch(lit & 0xff) {
6814                                                 case 1:
6815                                                                 if ( IC_TRUE(ifx) ) {
6816                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6817                                                                         emitSKPNZ;
6818                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6819                                                                 } else {
6820                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6821                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6822                                                                 }
6823                                                                 break;
6824                                                 case 0xff:
6825                                                                 if ( IC_TRUE(ifx) ) {
6826                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6827                                                                         emitSKPNZ;
6828                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6829                                                                 } else {
6830                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6831                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6832                                                                 }
6833                                                                 break;
6834                                                 default:
6835                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6836                                                                 if(lit)
6837                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6838                                                                 genSkip(ifx,'z');
6839                                         } // switch lit
6840
6841
6842                                         /* end of size == 1 */
6843                                         break;
6844               
6845                                 case 2:
6846                                         genc16bit2lit(left,lit,offset);
6847                                         genSkip(ifx,'z');
6848                                         break;
6849                                         /* end of size == 2 */
6850
6851                                 default:
6852                                         /* size is 4 */
6853                                         if(lit==0) {
6854                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6855                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6856                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6857                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6858                                                 genSkip(ifx,'z');
6859                                         } else {
6860                                                 /* search for patterns that can be optimized */
6861
6862                                                 genc16bit2lit(left,lit,0);
6863                                                 lit >>= 16;
6864                                                 if(lit) {
6865                                                                 if(IC_TRUE(ifx))
6866                                                                 emitSKPZ; // if hi word unequal
6867                                                                 else
6868                                                                 emitSKPNZ; // if hi word equal
6869                                                                 // fail early
6870                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6871                                                         genc16bit2lit(left,lit,2);
6872                                                         genSkip(ifx,'z');
6873                                                 } else {
6874                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6875                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6876                                                         genSkip(ifx,'z');
6877                                                 }
6878                                         }
6879                                                 pic16_emitpLabel(falselbl->key);
6880                                                 break;
6881
6882                         } // switch size
6883           
6884                         ifx->generated = 1;
6885                         goto release ;
6886             
6887
6888           } else if(AOP_TYPE(right) == AOP_CRY ) {
6889             /* we know the left is not a bit, but that the right is */
6890             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6891             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6892                       pic16_popGet(AOP(right),offset));
6893             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6894
6895             /* if the two are equal, then W will be 0 and the Z bit is set
6896              * we could test Z now, or go ahead and check the high order bytes if
6897              * the variable we're comparing is larger than a byte. */
6898
6899             while(--size)
6900               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6901
6902             if ( IC_TRUE(ifx) ) {
6903               emitSKPNZ;
6904               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6905               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6906             } else {
6907               emitSKPZ;
6908               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6909               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6910             }
6911
6912           } else {
6913             /* They're both variables that are larger than bits */
6914             int s = size;
6915
6916             tlbl = newiTempLabel(NULL);
6917
6918             while(size--) {
6919               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6920               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6921
6922               if ( IC_TRUE(ifx) ) {
6923                 if(size) {
6924                   emitSKPZ;
6925                 
6926                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6927
6928                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6929                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6930                 } else {
6931                   emitSKPNZ;
6932
6933                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6934
6935
6936                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6937                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6938                 }
6939               } else {
6940                 emitSKPZ;
6941
6942                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6943
6944                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6945                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6946               }
6947               offset++;
6948             }
6949             if(s>1 && IC_TRUE(ifx)) {
6950               pic16_emitpLabel(tlbl->key);
6951               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6952             }
6953           }
6954         }
6955         /* mark the icode as generated */
6956         ifx->generated = 1;
6957         goto release ;
6958     }
6959
6960     /* if they are both bit variables */
6961     if (AOP_TYPE(left) == AOP_CRY &&
6962         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6963         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6964         if(AOP_TYPE(right) == AOP_LIT){
6965             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6966             if(lit == 0L){
6967                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6968                 pic16_emitcode("cpl","c");
6969             } else if(lit == 1L) {
6970                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6971             } else {
6972                 pic16_emitcode("clr","c");
6973             }
6974             /* AOP_TYPE(right) == AOP_CRY */
6975         } else {
6976             symbol *lbl = newiTempLabel(NULL);
6977             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6978             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6979             pic16_emitcode("cpl","c");
6980             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6981         }
6982         /* c = 1 if egal */
6983         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6984             pic16_outBitC(result);
6985             goto release ;
6986         }
6987         if (ifx) {
6988             genIfxJump (ifx,"c");
6989             goto release ;
6990         }
6991         /* if the result is used in an arithmetic operation
6992         then put the result in place */
6993         pic16_outBitC(result);
6994     } else {
6995       
6996       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6997       gencjne(left,right,result,ifx);
6998 /*
6999       if(ifx) 
7000         gencjne(left,right,newiTempLabel(NULL));
7001       else {
7002         if(IC_TRUE(ifx)->key)
7003           gencjne(left,right,IC_TRUE(ifx)->key);
7004         else
7005           gencjne(left,right,IC_FALSE(ifx)->key);
7006         ifx->generated = 1;
7007         goto release ;
7008       }
7009       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7010         pic16_aopPut(AOP(result),"a",0);
7011         goto release ;
7012       }
7013
7014       if (ifx) {
7015         genIfxJump (ifx,"a");
7016         goto release ;
7017       }
7018 */
7019       /* if the result is used in an arithmetic operation
7020          then put the result in place */
7021 /*
7022       if (AOP_TYPE(result) != AOP_CRY) 
7023         pic16_outAcc(result);
7024 */
7025       /* leave the result in acc */
7026     }
7027
7028 release:
7029     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7030     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031     pic16_freeAsmop(result,NULL,ic,TRUE);
7032 }
7033 #endif
7034
7035 /*-----------------------------------------------------------------*/
7036 /* ifxForOp - returns the icode containing the ifx for operand     */
7037 /*-----------------------------------------------------------------*/
7038 static iCode *ifxForOp ( operand *op, iCode *ic )
7039 {
7040   FENTRY2;
7041
7042     /* if true symbol then needs to be assigned */
7043     if (IS_TRUE_SYMOP(op))
7044         return NULL ;
7045
7046     /* if this has register type condition and
7047     the next instruction is ifx with the same operand
7048     and live to of the operand is upto the ifx only then */
7049     if (ic->next
7050         && ic->next->op == IFX
7051         && IC_COND(ic->next)->key == op->key
7052         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7053         ) {
7054                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7055           return ic->next;
7056     }
7057
7058     /*
7059     if (ic->next &&
7060         ic->next->op == IFX &&
7061         IC_COND(ic->next)->key == op->key) {
7062       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7063       return ic->next;
7064     }
7065     */
7066
7067     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7068     if (ic->next &&
7069         ic->next->op == IFX)
7070       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7071
7072     if (ic->next &&
7073         ic->next->op == IFX &&
7074         IC_COND(ic->next)->key == op->key) {
7075       DEBUGpic16_emitcode ("; "," key is okay");
7076       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7077                            OP_SYMBOL(op)->liveTo,
7078                            ic->next->seq);
7079     }
7080
7081 #if 0
7082     /* the code below is completely untested
7083      * it just allows ulong2fs.c compile -- VR */
7084          
7085     ic = ic->next;
7086     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7087                                         __FILE__, __FUNCTION__, __LINE__);
7088         
7089     /* if this has register type condition and
7090     the next instruction is ifx with the same operand
7091     and live to of the operand is upto the ifx only then */
7092     if (ic->next &&
7093         ic->next->op == IFX &&
7094         IC_COND(ic->next)->key == op->key &&
7095         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7096         return ic->next;
7097
7098     if (ic->next &&
7099         ic->next->op == IFX &&
7100         IC_COND(ic->next)->key == op->key) {
7101       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7102       return ic->next;
7103     }
7104
7105     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7106                                         __FILE__, __FUNCTION__, __LINE__);
7107
7108 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7109 #endif
7110
7111     return NULL;
7112 }
7113 /*-----------------------------------------------------------------*/
7114 /* genAndOp - for && operation                                     */
7115 /*-----------------------------------------------------------------*/
7116 static void genAndOp (iCode *ic)
7117 {
7118   operand *left,*right, *result;
7119 /*     symbol *tlbl; */
7120
7121     FENTRY;
7122
7123     /* note here that && operations that are in an
7124     if statement are taken away by backPatchLabels
7125     only those used in arthmetic operations remain */
7126     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7127     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7128     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7129
7130     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7131
7132     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7133     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7134     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7135
7136     /* if both are bit variables */
7137 /*     if (AOP_TYPE(left) == AOP_CRY && */
7138 /*         AOP_TYPE(right) == AOP_CRY ) { */
7139 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7140 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7141 /*         pic16_outBitC(result); */
7142 /*     } else { */
7143 /*         tlbl = newiTempLabel(NULL); */
7144 /*         pic16_toBoolean(left);     */
7145 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7146 /*         pic16_toBoolean(right); */
7147 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7148 /*         pic16_outBitAcc(result); */
7149 /*     } */
7150
7151     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7152     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7153     pic16_freeAsmop(result,NULL,ic,TRUE);
7154 }
7155
7156
7157 /*-----------------------------------------------------------------*/
7158 /* genOrOp - for || operation                                      */
7159 /*-----------------------------------------------------------------*/
7160 /*
7161   tsd pic port -
7162   modified this code, but it doesn't appear to ever get called
7163 */
7164
7165 static void genOrOp (iCode *ic)
7166 {
7167   operand *left,*right, *result;
7168   symbol *tlbl;
7169
7170     FENTRY;  
7171
7172   /* note here that || operations that are in an
7173     if statement are taken away by backPatchLabels
7174     only those used in arthmetic operations remain */
7175     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7176     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7177     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7178
7179     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7180
7181     /* if both are bit variables */
7182     if (AOP_TYPE(left) == AOP_CRY &&
7183         AOP_TYPE(right) == AOP_CRY ) {
7184       pic16_emitcode("clrc","");
7185       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7186                AOP(left)->aopu.aop_dir,
7187                AOP(left)->aopu.aop_dir);
7188       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7189                AOP(right)->aopu.aop_dir,
7190                AOP(right)->aopu.aop_dir);
7191       pic16_emitcode("setc","");
7192
7193     } else {
7194         tlbl = newiTempLabel(NULL);
7195         pic16_toBoolean(left);
7196         emitSKPZ;
7197         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7198         pic16_toBoolean(right);
7199         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7200
7201         pic16_outBitAcc(result);
7202     }
7203
7204     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7205     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7206     pic16_freeAsmop(result,NULL,ic,TRUE);            
7207 }
7208
7209 /*-----------------------------------------------------------------*/
7210 /* isLiteralBit - test if lit == 2^n                               */
7211 /*-----------------------------------------------------------------*/
7212 static int isLiteralBit(unsigned long lit)
7213 {
7214     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7215     0x100L,0x200L,0x400L,0x800L,
7216     0x1000L,0x2000L,0x4000L,0x8000L,
7217     0x10000L,0x20000L,0x40000L,0x80000L,
7218     0x100000L,0x200000L,0x400000L,0x800000L,
7219     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7220     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7221     int idx;
7222     
7223     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7224     for(idx = 0; idx < 32; idx++)
7225         if(lit == pw[idx])
7226             return idx+1;
7227     return 0;
7228 }
7229
7230 /*-----------------------------------------------------------------*/
7231 /* continueIfTrue -                                                */
7232 /*-----------------------------------------------------------------*/
7233 static void continueIfTrue (iCode *ic)
7234 {
7235   FENTRY;
7236   if(IC_TRUE(ic))
7237     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7238   ic->generated = 1;
7239 }
7240
7241 /*-----------------------------------------------------------------*/
7242 /* jmpIfTrue -                                                     */
7243 /*-----------------------------------------------------------------*/
7244 static void jumpIfTrue (iCode *ic)
7245 {
7246   FENTRY;
7247   if(!IC_TRUE(ic))
7248     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7249   ic->generated = 1;
7250 }
7251
7252 /*-----------------------------------------------------------------*/
7253 /* jmpTrueOrFalse -                                                */
7254 /*-----------------------------------------------------------------*/
7255 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7256 {
7257   // ugly but optimized by peephole
7258   FENTRY;
7259   if(IC_TRUE(ic)){
7260     symbol *nlbl = newiTempLabel(NULL);
7261       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7262       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7263       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7264       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7265   } else {
7266     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7267     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7268   }
7269   ic->generated = 1;
7270 }
7271
7272 /*-----------------------------------------------------------------*/
7273 /* genAnd  - code for and                                          */
7274 /*-----------------------------------------------------------------*/
7275 static void genAnd (iCode *ic, iCode *ifx)
7276 {
7277   operand *left, *right, *result;
7278   int size, offset=0;  
7279   unsigned long lit = 0L;
7280   int bytelit = 0;
7281   resolvedIfx rIfx;
7282
7283     FENTRY;
7284     
7285   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7286   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7287   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7288
7289   resolveIfx(&rIfx,ifx);
7290
7291   /* if left is a literal & right is not then exchange them */
7292   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7293       AOP_NEEDSACC(left)) {
7294     operand *tmp = right ;
7295     right = left;
7296     left = tmp;
7297   }
7298
7299   /* if result = right then exchange them */
7300   if(pic16_sameRegs(AOP(result),AOP(right))){
7301     operand *tmp = right ;
7302     right = left;
7303     left = tmp;
7304   }
7305
7306   /* if right is bit then exchange them */
7307   if (AOP_TYPE(right) == AOP_CRY &&
7308       AOP_TYPE(left) != AOP_CRY){
7309     operand *tmp = right ;
7310     right = left;
7311     left = tmp;
7312   }
7313   if(AOP_TYPE(right) == AOP_LIT)
7314     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7315
7316   size = AOP_SIZE(result);
7317
7318   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7319
7320   // if(bit & yy)
7321   // result = bit & yy;
7322   if (AOP_TYPE(left) == AOP_CRY){
7323     // c = bit & literal;
7324     if(AOP_TYPE(right) == AOP_LIT){
7325       if(lit & 1) {
7326         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7327           // no change
7328           goto release;
7329         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7330       } else {
7331         // bit(result) = 0;
7332         if(size && (AOP_TYPE(result) == AOP_CRY)){
7333           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7334           goto release;
7335         }
7336         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7337           jumpIfTrue(ifx);
7338           goto release;
7339         }
7340         pic16_emitcode("clr","c");
7341       }
7342     } else {
7343       if (AOP_TYPE(right) == AOP_CRY){
7344         // c = bit & bit;
7345         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7346         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7347       } else {
7348         // c = bit & val;
7349         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7350         // c = lsb
7351         pic16_emitcode("rrc","a");
7352         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7353       }
7354     }
7355     // bit = c
7356     // val = c
7357     if(size)
7358       pic16_outBitC(result);
7359     // if(bit & ...)
7360     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7361       genIfxJump(ifx, "c");           
7362     goto release ;
7363   }
7364
7365   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7366   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7367   if((AOP_TYPE(right) == AOP_LIT) &&
7368      (AOP_TYPE(result) == AOP_CRY) &&
7369      (AOP_TYPE(left) != AOP_CRY)){
7370     int posbit = isLiteralBit(lit);
7371     /* left &  2^n */
7372     if(posbit){
7373       posbit--;
7374       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7375       // bit = left & 2^n
7376       if(size)
7377         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7378       // if(left &  2^n)
7379       else{
7380         if(ifx){
7381 /*
7382           if(IC_TRUE(ifx)) {
7383             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7384             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7385           } else {
7386             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7387             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7388           }
7389 */
7390         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7391         size = AOP_SIZE(left);
7392
7393         {
7394           int bp = posbit, ofs=0;
7395           
7396             while(bp > 7) {
7397               bp -= 8;
7398               ofs++;
7399             }
7400
7401           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7402                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7403
7404         }
7405 /*
7406           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7407                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7408 */
7409           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7410           
7411           ifx->generated = 1;
7412         }
7413         goto release;
7414       }
7415     } else {
7416       symbol *tlbl = newiTempLabel(NULL);
7417       int sizel = AOP_SIZE(left);
7418
7419       if(size)
7420         emitSETC;
7421
7422       while(sizel--) {
7423         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7424
7425           /* patch provided by Aaron Colwell */
7426           if((posbit = isLiteralBit(bytelit)) != 0) {
7427               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7428                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7429                                                 (posbit-1),0, PO_GPR_REGISTER));
7430
7431               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7432 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7433           } else {
7434               if (bytelit == 0xff) {
7435                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7436                    * a peephole could optimize it out -- VR */
7437                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7438               } else {
7439                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7440                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7441               }
7442
7443               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7444                             pic16_popGetLabel(tlbl->key));
7445           }
7446         
7447 #if 0
7448           /* old code, left here for reference -- VR 09/2004 */
7449           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7450           // byte ==  2^n ?
7451           if((posbit = isLiteralBit(bytelit)) != 0)
7452             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7453           else{
7454             if(bytelit != 0x0FFL)
7455               pic16_emitcode("anl","a,%s",
7456                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7457             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7458           }
7459 #endif
7460         }
7461         offset++;
7462       }
7463       // bit = left & literal
7464       if(size) {
7465         emitCLRC;
7466         pic16_emitpLabel(tlbl->key);
7467       }
7468       // if(left & literal)
7469       else {
7470         if(ifx) {
7471           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7472           ifx->generated = 1;
7473         }
7474         pic16_emitpLabel(tlbl->key);
7475         goto release;
7476       }
7477     }
7478
7479     pic16_outBitC(result);
7480     goto release ;
7481   }
7482
7483   /* if left is same as result */
7484   if(pic16_sameRegs(AOP(result),AOP(left))){
7485     int know_W = -1;
7486     for(;size--; offset++,lit>>=8) {
7487       if(AOP_TYPE(right) == AOP_LIT){
7488         switch(lit & 0xff) {
7489         case 0x00:
7490           /*  and'ing with 0 has clears the result */
7491 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7492           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7493           break;
7494         case 0xff:
7495           /* and'ing with 0xff is a nop when the result and left are the same */
7496           break;
7497
7498         default:
7499           {
7500             int p = pic16_my_powof2( (~lit) & 0xff );
7501             if(p>=0) {
7502               /* only one bit is set in the literal, so use a bcf instruction */
7503 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7504               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7505
7506             } else {
7507               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7508               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7509               if(know_W != (lit&0xff))
7510                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7511               know_W = lit &0xff;
7512               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7513             }
7514           }    
7515         }
7516       } else {
7517         if (AOP_TYPE(left) == AOP_ACC) {
7518           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7519         } else {                    
7520           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7521           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7522
7523         }
7524       }
7525     }
7526
7527   } else {
7528     // left & result in different registers
7529     if(AOP_TYPE(result) == AOP_CRY){
7530       // result = bit
7531       // if(size), result in bit
7532       // if(!size && ifx), conditional oper: if(left & right)
7533       symbol *tlbl = newiTempLabel(NULL);
7534       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7535       if(size)
7536         pic16_emitcode("setb","c");
7537       while(sizer--){
7538         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7539         pic16_emitcode("anl","a,%s",
7540                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7541         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7542         offset++;
7543       }
7544       if(size){
7545         CLRC;
7546         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7547         pic16_outBitC(result);
7548       } else if(ifx)
7549         jmpTrueOrFalse(ifx, tlbl);
7550     } else {
7551       for(;(size--);offset++) {
7552         // normal case
7553         // result = left & right
7554         if(AOP_TYPE(right) == AOP_LIT){
7555           int t = (lit >> (offset*8)) & 0x0FFL;
7556           switch(t) { 
7557           case 0x00:
7558             pic16_emitcode("clrf","%s",
7559                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7560             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7561             break;
7562           case 0xff:
7563             pic16_emitcode("movf","%s,w",
7564                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7565             pic16_emitcode("movwf","%s",
7566                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7567             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7568             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7569             break;
7570           default:
7571             pic16_emitcode("movlw","0x%x",t);
7572             pic16_emitcode("andwf","%s,w",
7573                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7574             pic16_emitcode("movwf","%s",
7575                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7576               
7577             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7578             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7579             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7580           }
7581           continue;
7582         }
7583
7584         if (AOP_TYPE(left) == AOP_ACC) {
7585           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7586           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7587         } else {
7588           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7589           pic16_emitcode("andwf","%s,w",
7590                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7591           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7592           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7593         }
7594         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7595         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7596       }
7597     }
7598   }
7599
7600   release :
7601     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7602   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7603   pic16_freeAsmop(result,NULL,ic,TRUE);     
7604 }
7605
7606 /*-----------------------------------------------------------------*/
7607 /* genOr  - code for or                                            */
7608 /*-----------------------------------------------------------------*/
7609 static void genOr (iCode *ic, iCode *ifx)
7610 {
7611     operand *left, *right, *result;
7612     int size, offset=0;
7613     unsigned long lit = 0L;
7614
7615     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7616
7617     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7618     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7619     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7620
7621     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7622
7623     /* if left is a literal & right is not then exchange them */
7624     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7625         AOP_NEEDSACC(left)) {
7626         operand *tmp = right ;
7627         right = left;
7628         left = tmp;
7629     }
7630
7631     /* if result = right then exchange them */
7632     if(pic16_sameRegs(AOP(result),AOP(right))){
7633         operand *tmp = right ;
7634         right = left;
7635         left = tmp;
7636     }
7637
7638     /* if right is bit then exchange them */
7639     if (AOP_TYPE(right) == AOP_CRY &&
7640         AOP_TYPE(left) != AOP_CRY){
7641         operand *tmp = right ;
7642         right = left;
7643         left = tmp;
7644     }
7645
7646     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7647
7648     if(AOP_TYPE(right) == AOP_LIT)
7649         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7650
7651     size = AOP_SIZE(result);
7652
7653     // if(bit | yy)
7654     // xx = bit | yy;
7655     if (AOP_TYPE(left) == AOP_CRY){
7656         if(AOP_TYPE(right) == AOP_LIT){
7657             // c = bit & literal;
7658             if(lit){
7659                 // lit != 0 => result = 1
7660                 if(AOP_TYPE(result) == AOP_CRY){
7661                   if(size)
7662                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7663                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7664                   //     AOP(result)->aopu.aop_dir,
7665                   //     AOP(result)->aopu.aop_dir);
7666                     else if(ifx)
7667                         continueIfTrue(ifx);
7668                     goto release;
7669                 }
7670             } else {
7671                 // lit == 0 => result = left
7672                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7673                     goto release;
7674                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7675             }
7676         } else {
7677             if (AOP_TYPE(right) == AOP_CRY){
7678               if(pic16_sameRegs(AOP(result),AOP(left))){
7679                 // c = bit | bit;
7680                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7681                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7682                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7683
7684                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7685                          AOP(result)->aopu.aop_dir,
7686                          AOP(result)->aopu.aop_dir);
7687                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7688                          AOP(right)->aopu.aop_dir,
7689                          AOP(right)->aopu.aop_dir);
7690                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7691                          AOP(result)->aopu.aop_dir,
7692                          AOP(result)->aopu.aop_dir);
7693               } else {
7694                 if( AOP_TYPE(result) == AOP_ACC) {
7695                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7696                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7697                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7698                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7699
7700                 } else {
7701
7702                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7703                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7704                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7705                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7706
7707                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7708                                  AOP(result)->aopu.aop_dir,
7709                                  AOP(result)->aopu.aop_dir);
7710                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7711                                  AOP(right)->aopu.aop_dir,
7712                                  AOP(right)->aopu.aop_dir);
7713                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7714                                  AOP(left)->aopu.aop_dir,
7715                                  AOP(left)->aopu.aop_dir);
7716                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7717                                  AOP(result)->aopu.aop_dir,
7718                                  AOP(result)->aopu.aop_dir);
7719                 }
7720               }
7721             } else {
7722                 // c = bit | val;
7723                 symbol *tlbl = newiTempLabel(NULL);
7724                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7725
7726
7727                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7728                 if( AOP_TYPE(right) == AOP_ACC) {
7729                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7730                   emitSKPNZ;
7731                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7732                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7733                 }
7734
7735
7736
7737                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7738                     pic16_emitcode(";XXX setb","c");
7739                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7740                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7741                 pic16_toBoolean(right);
7742                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7743                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7744                     jmpTrueOrFalse(ifx, tlbl);
7745                     goto release;
7746                 } else {
7747                     CLRC;
7748                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7749                 }
7750             }
7751         }
7752         // bit = c
7753         // val = c
7754         if(size)
7755             pic16_outBitC(result);
7756         // if(bit | ...)
7757         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7758             genIfxJump(ifx, "c");           
7759         goto release ;
7760     }
7761
7762     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7763     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7764     if((AOP_TYPE(right) == AOP_LIT) &&
7765        (AOP_TYPE(result) == AOP_CRY) &&
7766        (AOP_TYPE(left) != AOP_CRY)){
7767         if(lit){
7768           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7769             // result = 1
7770             if(size)
7771                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7772             else 
7773                 continueIfTrue(ifx);
7774             goto release;
7775         } else {
7776           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7777             // lit = 0, result = boolean(left)
7778             if(size)
7779                 pic16_emitcode(";XXX setb","c");
7780             pic16_toBoolean(right);
7781             if(size){
7782                 symbol *tlbl = newiTempLabel(NULL);
7783                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7784                 CLRC;
7785                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7786             } else {
7787                 genIfxJump (ifx,"a");
7788                 goto release;
7789             }
7790         }
7791         pic16_outBitC(result);
7792         goto release ;
7793     }
7794
7795     /* if left is same as result */
7796     if(pic16_sameRegs(AOP(result),AOP(left))){
7797       int know_W = -1;
7798       for(;size--; offset++,lit>>=8) {
7799         if(AOP_TYPE(right) == AOP_LIT){
7800           if((lit & 0xff) == 0)
7801             /*  or'ing with 0 has no effect */
7802             continue;
7803           else {
7804             int p = pic16_my_powof2(lit & 0xff);
7805             if(p>=0) {
7806               /* only one bit is set in the literal, so use a bsf instruction */
7807               pic16_emitpcode(POC_BSF,
7808                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7809             } else {
7810               if(know_W != (lit & 0xff))
7811                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7812               know_W = lit & 0xff;
7813               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7814             }
7815                     
7816           }
7817         } else {
7818           if (AOP_TYPE(left) == AOP_ACC) {
7819             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7820 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7821           } else {                  
7822             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7823             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7824
7825 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7826 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7827
7828           }
7829         }
7830       }
7831     } else {
7832         // left & result in different registers
7833         if(AOP_TYPE(result) == AOP_CRY){
7834             // result = bit
7835             // if(size), result in bit
7836             // if(!size && ifx), conditional oper: if(left | right)
7837             symbol *tlbl = newiTempLabel(NULL);
7838             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7839             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7840
7841
7842             if(size)
7843                 pic16_emitcode(";XXX setb","c");
7844             while(sizer--){
7845                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7846                 pic16_emitcode(";XXX orl","a,%s",
7847                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7848                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7849                 offset++;
7850             }
7851             if(size){
7852                 CLRC;
7853                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7854                 pic16_outBitC(result);
7855             } else if(ifx)
7856                 jmpTrueOrFalse(ifx, tlbl);
7857         } else for(;(size--);offset++){
7858           // normal case
7859           // result = left & right
7860           if(AOP_TYPE(right) == AOP_LIT){
7861             int t = (lit >> (offset*8)) & 0x0FFL;
7862             switch(t) { 
7863             case 0x00:
7864               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7865               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7866
7867 //            pic16_emitcode("movf","%s,w",
7868 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7869 //            pic16_emitcode("movwf","%s",
7870 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7871               break;
7872             default:
7873               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7874               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7875               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7876
7877 //            pic16_emitcode("movlw","0x%x",t);
7878 //            pic16_emitcode("iorwf","%s,w",
7879 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7880 //            pic16_emitcode("movwf","%s",
7881 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7882               
7883             }
7884             continue;
7885           }
7886
7887           // faster than result <- left, anl result,right
7888           // and better if result is SFR
7889           if (AOP_TYPE(left) == AOP_ACC) {
7890             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7891 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7892           } else {
7893             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7894             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7895
7896 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897 //          pic16_emitcode("iorwf","%s,w",
7898 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7899           }
7900           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7901 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7902         }
7903     }
7904
7905 release :
7906     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7907     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7908     pic16_freeAsmop(result,NULL,ic,TRUE);     
7909 }
7910
7911 /*-----------------------------------------------------------------*/
7912 /* genXor - code for xclusive or                                   */
7913 /*-----------------------------------------------------------------*/
7914 static void genXor (iCode *ic, iCode *ifx)
7915 {
7916   operand *left, *right, *result;
7917   int size, offset=0;
7918   unsigned long lit = 0L;
7919
7920   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7921
7922   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7923   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7924   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7925
7926   /* if left is a literal & right is not ||
7927      if left needs acc & right does not */
7928   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7929       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7930     operand *tmp = right ;
7931     right = left;
7932     left = tmp;
7933   }
7934
7935   /* if result = right then exchange them */
7936   if(pic16_sameRegs(AOP(result),AOP(right))){
7937     operand *tmp = right ;
7938     right = left;
7939     left = tmp;
7940   }
7941
7942   /* if right is bit then exchange them */
7943   if (AOP_TYPE(right) == AOP_CRY &&
7944       AOP_TYPE(left) != AOP_CRY){
7945     operand *tmp = right ;
7946     right = left;
7947     left = tmp;
7948   }
7949   if(AOP_TYPE(right) == AOP_LIT)
7950     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7951
7952   size = AOP_SIZE(result);
7953
7954   // if(bit ^ yy)
7955   // xx = bit ^ yy;
7956   if (AOP_TYPE(left) == AOP_CRY){
7957     if(AOP_TYPE(right) == AOP_LIT){
7958       // c = bit & literal;
7959       if(lit>>1){
7960         // lit>>1  != 0 => result = 1
7961         if(AOP_TYPE(result) == AOP_CRY){
7962           if(size)
7963             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7964             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7965           else if(ifx)
7966             continueIfTrue(ifx);
7967           goto release;
7968         }
7969         pic16_emitcode("setb","c");
7970       } else{
7971         // lit == (0 or 1)
7972         if(lit == 0){
7973           // lit == 0, result = left
7974           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7975             goto release;
7976           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7977         } else{
7978           // lit == 1, result = not(left)
7979           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7980             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7981             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7982             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7983             goto release;
7984           } else {
7985             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7986             pic16_emitcode("cpl","c");
7987           }
7988         }
7989       }
7990
7991     } else {
7992       // right != literal
7993       symbol *tlbl = newiTempLabel(NULL);
7994       if (AOP_TYPE(right) == AOP_CRY){
7995         // c = bit ^ bit;
7996         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7997       }
7998       else{
7999         int sizer = AOP_SIZE(right);
8000         // c = bit ^ val
8001         // if val>>1 != 0, result = 1
8002         pic16_emitcode("setb","c");
8003         while(sizer){
8004           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8005           if(sizer == 1)
8006             // test the msb of the lsb
8007             pic16_emitcode("anl","a,#0xfe");
8008           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8009           sizer--;
8010         }
8011         // val = (0,1)
8012         pic16_emitcode("rrc","a");
8013       }
8014       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8015       pic16_emitcode("cpl","c");
8016       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8017     }
8018     // bit = c
8019     // val = c
8020     if(size)
8021       pic16_outBitC(result);
8022     // if(bit | ...)
8023     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8024       genIfxJump(ifx, "c");           
8025     goto release ;
8026   }
8027
8028   if(pic16_sameRegs(AOP(result),AOP(left))){
8029     /* if left is same as result */
8030     for(;size--; offset++) {
8031       if(AOP_TYPE(right) == AOP_LIT){
8032         int t  = (lit >> (offset*8)) & 0x0FFL;
8033         if(t == 0x00L)
8034           continue;
8035         else
8036           if (IS_AOP_PREG(left)) {
8037             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8038             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8039             pic16_aopPut(AOP(result),"a",offset);
8040           } else {
8041             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8042             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8043             pic16_emitcode("xrl","%s,%s",
8044                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8045                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8046           }
8047       } else {
8048         if (AOP_TYPE(left) == AOP_ACC)
8049           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8050         else {
8051           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8052           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8053 /*
8054           if (IS_AOP_PREG(left)) {
8055             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8056             pic16_aopPut(AOP(result),"a",offset);
8057           } else
8058             pic16_emitcode("xrl","%s,a",
8059                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8060 */
8061         }
8062       }
8063     }
8064   } else {
8065     // left & result in different registers
8066     if(AOP_TYPE(result) == AOP_CRY){
8067       // result = bit
8068       // if(size), result in bit
8069       // if(!size && ifx), conditional oper: if(left ^ right)
8070       symbol *tlbl = newiTempLabel(NULL);
8071       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8072       if(size)
8073         pic16_emitcode("setb","c");
8074       while(sizer--){
8075         if((AOP_TYPE(right) == AOP_LIT) &&
8076            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8077           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8078         } else {
8079           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8080           pic16_emitcode("xrl","a,%s",
8081                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8082         }
8083         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8084         offset++;
8085       }
8086       if(size){
8087         CLRC;
8088         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8089         pic16_outBitC(result);
8090       } else if(ifx)
8091         jmpTrueOrFalse(ifx, tlbl);
8092     } else for(;(size--);offset++){
8093       // normal case
8094       // result = left & right
8095       if(AOP_TYPE(right) == AOP_LIT){
8096         int t = (lit >> (offset*8)) & 0x0FFL;
8097         switch(t) { 
8098         case 0x00:
8099           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8100           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8101           pic16_emitcode("movf","%s,w",
8102                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8103           pic16_emitcode("movwf","%s",
8104                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8105           break;
8106         case 0xff:
8107           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8108           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8109           pic16_emitcode("comf","%s,w",
8110                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8111           pic16_emitcode("movwf","%s",
8112                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8113           break;
8114         default:
8115           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8116           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8117           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8118           pic16_emitcode("movlw","0x%x",t);
8119           pic16_emitcode("xorwf","%s,w",
8120                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8121           pic16_emitcode("movwf","%s",
8122                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8123
8124         }
8125         continue;
8126       }
8127
8128       // faster than result <- left, anl result,right
8129       // and better if result is SFR
8130       if (AOP_TYPE(left) == AOP_ACC) {
8131         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8132         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8133       } else {
8134         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8135         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8136         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8137         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8138       }
8139       if ( AOP_TYPE(result) != AOP_ACC){
8140         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8141         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8142       }
8143     }
8144   }
8145
8146   release :
8147     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8148   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8149   pic16_freeAsmop(result,NULL,ic,TRUE);     
8150 }
8151
8152 /*-----------------------------------------------------------------*/
8153 /* genInline - write the inline code out                           */
8154 /*-----------------------------------------------------------------*/
8155 static void genInline (iCode *ic)
8156 {
8157   char *buffer, *bp, *bp1;
8158     
8159         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8160
8161         _G.inLine += (!options.asmpeep);
8162
8163         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8164         strcpy(buffer,IC_INLINE(ic));
8165         
8166         while((bp1=strstr(bp, "\\n"))) {
8167           *bp1++ = '\n';
8168           *bp1++ = ' ';
8169           bp = bp1;
8170         }
8171         bp = bp1 = buffer;
8172
8173 #if 0
8174   /* This is an experimental code for #pragma inline
8175      and is temporarily disabled for 2.5.0 release */
8176         if(asmInlineMap)
8177         {
8178           symbol *sym;
8179           char *s;
8180           char *cbuf;
8181           int cblen;
8182
8183             cbuf = Safe_strdup(buffer);
8184             cblen = strlen(buffer)+1;
8185             memset(cbuf, 0, cblen);
8186
8187             bp = buffer;
8188             bp1 = cbuf;
8189             while(*bp) {
8190               if(*bp != '%')*bp1++ = *bp++;
8191               else {
8192                 int i;
8193
8194                   bp++;
8195                   i = *bp - '0';
8196                   if(i>elementsInSet(asmInlineMap))break;
8197                   
8198                   bp++;
8199                   s = indexSet(asmInlineMap, i);
8200                   DEBUGpc("searching symbol s = `%s'", s);
8201                   sym = findSym(SymbolTab, NULL, s);
8202
8203                   if(sym->reqv) {
8204                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8205                   } else {
8206                     strcat(bp1, sym->rname);
8207                   }
8208                   
8209                   while(*bp1)bp1++;
8210               }
8211               
8212               if(strlen(bp1) > cblen - 16) {
8213                 int i = strlen(cbuf);
8214                 cblen += 50;
8215                 cbuf = realloc(cbuf, cblen);
8216                 memset(cbuf+i, 0, 50);
8217                 bp1 = cbuf + i;
8218               }
8219             }
8220             
8221             free(buffer);
8222             buffer = Safe_strdup( cbuf );
8223             free(cbuf);
8224             
8225             bp = bp1 = buffer;
8226         }
8227 #endif  /* 0 */
8228
8229         /* emit each line as a code */
8230         while (*bp) {
8231                 if (*bp == '\n') {
8232                         *bp++ = '\0';
8233
8234                         if(*bp1)
8235                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8236                         bp1 = bp;
8237                 } else {
8238                         if (*bp == ':') {
8239                                 bp++;
8240                                 *bp = '\0';
8241                                 bp++;
8242
8243                                 /* print label, use this special format with NULL directive
8244                                  * to denote that the argument should not be indented with tab */
8245                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8246                                 bp1 = bp;
8247                         } if (*bp == ';') {
8248                                 /* advance to end of line (prevent splitting of comments at ':' */
8249                                 while (*bp && *bp != '\n') {
8250                                         bp++;
8251                                 } // while
8252                         } else
8253                                 bp++;
8254                 }
8255         }
8256
8257         if ((bp1 != bp) && *bp1)
8258                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8259
8260
8261     Safe_free(buffer);
8262
8263     _G.inLine -= (!options.asmpeep);
8264 }
8265
8266 /*-----------------------------------------------------------------*/
8267 /* genRRC - rotate right with carry                                */
8268 /*-----------------------------------------------------------------*/
8269 static void genRRC (iCode *ic)
8270 {
8271   operand *left , *result ;
8272   int size, offset = 0, same;
8273
8274   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8275
8276   /* rotate right with carry */
8277   left = IC_LEFT(ic);
8278   result=IC_RESULT(ic);
8279   pic16_aopOp (left,ic,FALSE);
8280   pic16_aopOp (result,ic,TRUE);
8281
8282   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8283
8284   same = pic16_sameRegs(AOP(result),AOP(left));
8285
8286   size = AOP_SIZE(result);    
8287
8288   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8289
8290   /* get the lsb and put it into the carry */
8291   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8292
8293   offset = 0 ;
8294
8295   while(size--) {
8296
8297     if(same) {
8298       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8299     } else {
8300       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8301       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8302     }
8303
8304     offset++;
8305   }
8306
8307   pic16_freeAsmop(left,NULL,ic,TRUE);
8308   pic16_freeAsmop(result,NULL,ic,TRUE);
8309 }
8310
8311 /*-----------------------------------------------------------------*/
8312 /* genRLC - generate code for rotate left with carry               */
8313 /*-----------------------------------------------------------------*/
8314 static void genRLC (iCode *ic)
8315 {    
8316   operand *left , *result ;
8317   int size, offset = 0;
8318   int same;
8319
8320   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8321   /* rotate right with carry */
8322   left = IC_LEFT(ic);
8323   result=IC_RESULT(ic);
8324   pic16_aopOp (left,ic,FALSE);
8325   pic16_aopOp (result,ic,TRUE);
8326
8327   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8328
8329   same = pic16_sameRegs(AOP(result),AOP(left));
8330
8331   /* move it to the result */
8332   size = AOP_SIZE(result);    
8333
8334   /* get the msb and put it into the carry */
8335   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8336
8337   offset = 0 ;
8338
8339   while(size--) {
8340
8341     if(same) {
8342       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8343     } else {
8344       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8345       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8346     }
8347
8348     offset++;
8349   }
8350
8351
8352   pic16_freeAsmop(left,NULL,ic,TRUE);
8353   pic16_freeAsmop(result,NULL,ic,TRUE);
8354 }
8355
8356
8357 /* gpasm can get the highest order bit with HIGH/UPPER
8358  * so the following probably is not needed -- VR */
8359  
8360 /*-----------------------------------------------------------------*/
8361 /* genGetHbit - generates code get highest order bit               */
8362 /*-----------------------------------------------------------------*/
8363 static void genGetHbit (iCode *ic)
8364 {
8365     operand *left, *result;
8366     left = IC_LEFT(ic);
8367     result=IC_RESULT(ic);
8368     pic16_aopOp (left,ic,FALSE);
8369     pic16_aopOp (result,ic,FALSE);
8370
8371     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8372     /* get the highest order byte into a */
8373     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8374     if(AOP_TYPE(result) == AOP_CRY){
8375         pic16_emitcode("rlc","a");
8376         pic16_outBitC(result);
8377     }
8378     else{
8379         pic16_emitcode("rl","a");
8380         pic16_emitcode("anl","a,#0x01");
8381         pic16_outAcc(result);
8382     }
8383
8384
8385     pic16_freeAsmop(left,NULL,ic,TRUE);
8386     pic16_freeAsmop(result,NULL,ic,TRUE);
8387 }
8388
8389 #if 0
8390 /*-----------------------------------------------------------------*/
8391 /* AccRol - rotate left accumulator by known count                 */
8392 /*-----------------------------------------------------------------*/
8393 static void AccRol (int shCount)
8394 {
8395     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8396     shCount &= 0x0007;              // shCount : 0..7
8397     switch(shCount){
8398         case 0 :
8399             break;
8400         case 1 :
8401             pic16_emitcode("rl","a");
8402             break;
8403         case 2 :
8404             pic16_emitcode("rl","a");
8405             pic16_emitcode("rl","a");
8406             break;
8407         case 3 :
8408             pic16_emitcode("swap","a");
8409             pic16_emitcode("rr","a");
8410             break;
8411         case 4 :
8412             pic16_emitcode("swap","a");
8413             break;
8414         case 5 :
8415             pic16_emitcode("swap","a");
8416             pic16_emitcode("rl","a");
8417             break;
8418         case 6 :
8419             pic16_emitcode("rr","a");
8420             pic16_emitcode("rr","a");
8421             break;
8422         case 7 :
8423             pic16_emitcode("rr","a");
8424             break;
8425     }
8426 }
8427 #endif
8428
8429 /*-----------------------------------------------------------------*/
8430 /* AccLsh - left shift accumulator by known count                  */
8431 /*-----------------------------------------------------------------*/
8432 static void AccLsh (int shCount, int doMask)
8433 {
8434         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8435         switch(shCount){
8436                 case 0 :
8437                         return;
8438                         break;
8439                 case 1 :
8440                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8441                         break;
8442                 case 2 :
8443                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445                         break;
8446                 case 3 :
8447                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8448                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         break;
8450                 case 4 :
8451                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8452                         break;
8453                 case 5 :
8454                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8455                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8456                         break;
8457                 case 6 :
8458                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8459                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460                         break;
8461                 case 7 :
8462                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463                         break;
8464         }
8465         if (doMask) {
8466                 /* no masking is required in genPackBits */
8467                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8468         }
8469 }
8470
8471 /*-----------------------------------------------------------------*/
8472 /* AccRsh - right shift accumulator by known count                 */
8473 /*-----------------------------------------------------------------*/
8474 static void AccRsh (int shCount, int andmask)
8475 {
8476         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8477         switch(shCount){
8478                 case 0 :
8479                         return; break;
8480                 case 1 :
8481                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8482                         break;
8483                 case 2 :
8484                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8485                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8486                         break;
8487                 case 3 :
8488                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8489                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8490                         break;
8491                 case 4 :
8492                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8493                         break;
8494                 case 5 :
8495                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8496                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8497                         break;
8498                 case 6 :
8499                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8500                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8501                         break;
8502                 case 7 :
8503                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8504                         break;
8505         }
8506         
8507         if(andmask)
8508                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8509         else
8510                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8511 }
8512
8513 #if 0
8514 /*-----------------------------------------------------------------*/
8515 /* AccSRsh - signed right shift accumulator by known count                 */
8516 /*-----------------------------------------------------------------*/
8517 static void AccSRsh (int shCount)
8518 {
8519     symbol *tlbl ;
8520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8521     if(shCount != 0){
8522         if(shCount == 1){
8523             pic16_emitcode("mov","c,acc.7");
8524             pic16_emitcode("rrc","a");
8525         } else if(shCount == 2){
8526             pic16_emitcode("mov","c,acc.7");
8527             pic16_emitcode("rrc","a");
8528             pic16_emitcode("mov","c,acc.7");
8529             pic16_emitcode("rrc","a");
8530         } else {
8531             tlbl = newiTempLabel(NULL);
8532             /* rotate right accumulator */
8533             AccRol(8 - shCount);
8534             /* and kill the higher order bits */
8535             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8536             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8537             pic16_emitcode("orl","a,#0x%02x",
8538                      (unsigned char)~SRMask[shCount]);
8539             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8540         }
8541     }
8542 }
8543 #endif
8544
8545 /*-----------------------------------------------------------------*/
8546 /* shiftR1Left2Result - shift right one byte from left to result   */
8547 /*-----------------------------------------------------------------*/
8548 static void shiftR1Left2ResultSigned (operand *left, int offl,
8549                                 operand *result, int offr,
8550                                 int shCount)
8551 {
8552   int same;
8553
8554   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8555
8556   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8557
8558   switch(shCount) {
8559   case 1:
8560     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8561     if(same) 
8562       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8563     else {
8564       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8565       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8566     }
8567
8568     break;
8569   case 2:
8570
8571     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8572     if(same) 
8573       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8574     else {
8575       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8576       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8577     }
8578     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8579     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8580
8581     break;
8582
8583   case 3:
8584     if(same)
8585       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8586     else {
8587       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8588       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8589     }
8590
8591     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8592     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8593     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8594
8595     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8596     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8597
8598     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8599     break;
8600
8601   case 4:
8602     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8603     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8604     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8605     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8606     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8607     break;
8608   case 5:
8609     if(same) {
8610       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8611     } else {
8612       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8613       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8614     }
8615     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8616     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8617     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8618     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8619     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8620     break;
8621
8622   case 6:
8623     if(same) {
8624       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8625       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8626       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8627       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8628       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8629       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8630     } else {
8631       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8632       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8633       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8634       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8635       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8636     }
8637     break;
8638
8639   case 7:
8640     if(same) {
8641       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8642       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8643       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8644       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8645     } else {
8646       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8647       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8648       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8649     }
8650
8651   default:
8652     break;
8653   }
8654 }
8655
8656 /*-----------------------------------------------------------------*/
8657 /* shiftR1Left2Result - shift right one byte from left to result   */
8658 /*-----------------------------------------------------------------*/
8659 static void shiftR1Left2Result (operand *left, int offl,
8660                                 operand *result, int offr,
8661                                 int shCount, int sign)
8662 {
8663   int same;
8664
8665   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8666
8667   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8668
8669   /* Copy the msb into the carry if signed. */
8670   if(sign) {
8671     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8672     return;
8673   }
8674
8675
8676
8677   switch(shCount) {
8678   case 1:
8679     emitCLRC;
8680     if(same) 
8681       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8682     else {
8683       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8684       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8685     }
8686     break;
8687   case 2:
8688     emitCLRC;
8689     if(same) {
8690       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8691     } else {
8692       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8693       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8694     }
8695     emitCLRC;
8696     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8697
8698     break;
8699   case 3:
8700     if(same)
8701       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8702     else {
8703       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8704       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8705     }
8706
8707     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8708     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8709     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8710     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711     break;
8712       
8713   case 4:
8714     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8715     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8716     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8717     break;
8718
8719   case 5:
8720     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8721     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8722     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8723     //emitCLRC;
8724     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8725
8726     break;
8727   case 6:
8728
8729     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8730     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8731     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8732     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8733     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8734     break;
8735
8736   case 7:
8737
8738     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8739     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8740     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8741
8742     break;
8743
8744   default:
8745     break;
8746   }
8747 }
8748
8749 /*-----------------------------------------------------------------*/
8750 /* shiftL1Left2Result - shift left one byte from left to result    */
8751 /*-----------------------------------------------------------------*/
8752 static void shiftL1Left2Result (operand *left, int offl,
8753                                 operand *result, int offr, int shCount)
8754 {
8755   int same;
8756
8757   //    char *l;
8758   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8759
8760   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8761   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8762     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8763     //    MOVA(l);
8764     /* shift left accumulator */
8765     //AccLsh(shCount, 1); // don't comment out just yet...
8766   //    pic16_aopPut(AOP(result),"a",offr);
8767
8768   switch(shCount) {
8769   case 1:
8770     /* Shift left 1 bit position */
8771     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8772     if(same) {
8773       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8774     } else {
8775       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8776       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8777     }
8778     break;
8779   case 2:
8780     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8781     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8782     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8783     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8784     break;
8785   case 3:
8786     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8787     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8788     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8789     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8790     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8791     break;
8792   case 4:
8793     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8794     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8795     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8796     break;
8797   case 5:
8798     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8799     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8800     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8801     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8802     break;
8803   case 6:
8804     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8805     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8806     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8807     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8808     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8809     break;
8810   case 7:
8811     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8812     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8813     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8814     break;
8815
8816   default:
8817     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8818   }
8819
8820 }
8821
8822 /*-----------------------------------------------------------------*/
8823 /* movLeft2Result - move byte from left to result                  */
8824 /*-----------------------------------------------------------------*/
8825 static void movLeft2Result (operand *left, int offl,
8826                             operand *result, int offr)
8827 {
8828   char *l;
8829   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8830   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8831     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8832
8833     if (*l == '@' && (IS_AOP_PREG(result))) {
8834       pic16_emitcode("mov","a,%s",l);
8835       pic16_aopPut(AOP(result),"a",offr);
8836     } else {
8837       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8838       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8839     }
8840   }
8841 }
8842
8843 /*-----------------------------------------------------------------*/
8844 /* shiftL2Left2Result - shift left two bytes from left to result   */
8845 /*-----------------------------------------------------------------*/
8846 static void shiftL2Left2Result (operand *left, int offl,
8847                                 operand *result, int offr, int shCount)
8848 {
8849   int same = pic16_sameRegs(AOP(result), AOP(left));
8850   int i;
8851
8852   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8853
8854   if (same && (offl != offr)) { // shift bytes
8855     if (offr > offl) {
8856        for(i=1;i>-1;i--) {
8857          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8858          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8859        }
8860     } else { // just treat as different later on
8861                 same = 0;
8862     }
8863   }
8864
8865   if(same) {
8866     switch(shCount) {
8867     case 0:
8868       break;
8869     case 1:
8870     case 2:
8871     case 3:
8872
8873       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8874       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8875       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8876
8877       while(--shCount) {
8878                 emitCLRC;
8879                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8880                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8881       }
8882
8883       break;
8884     case 4:
8885     case 5:
8886       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8887       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8888       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8889       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8890       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8891       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8892       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8893       if(shCount >=5) {
8894                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8895                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8896       }
8897       break;
8898     case 6:
8899       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8900       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8901       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8902       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8903       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8904       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8905       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8906       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8907       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8909       break;
8910     case 7:
8911       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8912       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8913       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8914       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8915       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8916     }
8917
8918   } else {
8919     switch(shCount) {
8920     case 0:
8921       break;
8922     case 1:
8923     case 2:
8924     case 3:
8925       /* note, use a mov/add for the shift since the mov has a
8926          chance of getting optimized out */
8927       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8928       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8929       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8930       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8931       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8932
8933       while(--shCount) {
8934                 emitCLRC;
8935                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8936                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8937       }
8938       break;
8939
8940     case 4:
8941     case 5:
8942       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8943       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8944       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8945       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8946       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8947       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8948       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8950
8951
8952       if(shCount == 5) {
8953                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8954                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8955       }
8956       break;
8957     case 6:
8958       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8959       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8960       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8961       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8962
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_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8966       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8967       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8969       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8971       break;
8972     case 7:
8973       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8977       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8978     }
8979   }
8980
8981 }
8982 /*-----------------------------------------------------------------*/
8983 /* shiftR2Left2Result - shift right two bytes from left to result  */
8984 /*-----------------------------------------------------------------*/
8985 static void shiftR2Left2Result (operand *left, int offl,
8986                                 operand *result, int offr,
8987                                 int shCount, int sign)
8988 {
8989   int same = pic16_sameRegs(AOP(result), AOP(left));
8990   int i;
8991   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8992
8993   if (same && (offl != offr)) { // shift right bytes
8994     if (offr < offl) {
8995        for(i=0;i<2;i++) {
8996          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8997          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8998        }
8999     } else { // just treat as different later on
9000                 same = 0;
9001     }
9002   }
9003
9004   switch(shCount) {
9005   case 0:
9006     break;
9007   case 1:
9008   case 2:
9009   case 3:
9010     if(sign)
9011       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9012     else
9013       emitCLRC;
9014
9015     if(same) {
9016       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9017       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9018     } else {
9019       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9020       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9021       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9022       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9023     }
9024
9025     while(--shCount) {
9026       if(sign)
9027                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9028       else
9029                 emitCLRC;
9030       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9032     }
9033     break;
9034   case 4:
9035   case 5:
9036     if(same) {
9037
9038       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9039       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9040       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9041
9042       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9043       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9045       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9046     } else {
9047       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9048       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9049       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9050
9051       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9052       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9053       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9054       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9055       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9056     }
9057
9058     if(shCount >=5) {
9059       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9060       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9061     }
9062
9063     if(sign) {
9064       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9065       pic16_emitpcode(POC_BTFSC, 
9066                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9067       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9068     }
9069
9070     break;
9071
9072   case 6:
9073     if(same) {
9074
9075       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9076       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9077
9078       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9079       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9080       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9081       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9082       if(sign) {
9083         pic16_emitpcode(POC_BTFSC, 
9084                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9085         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9086       }
9087       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9088       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9089       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9090       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9091     } else {
9092       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9093       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9094       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9095       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9096       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9097       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9098       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9099       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9100       if(sign) {
9101         pic16_emitpcode(POC_BTFSC, 
9102                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9103         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9104       }
9105       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9106       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9107
9108         
9109     }
9110
9111     break;
9112   case 7:
9113     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9114     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9115     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9117     if(sign) {
9118       emitSKPNC;
9119       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9120     } else 
9121       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9122   }
9123 }
9124
9125
9126 /*-----------------------------------------------------------------*/
9127 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9128 /*-----------------------------------------------------------------*/
9129 static void shiftLLeftOrResult (operand *left, int offl,
9130                                 operand *result, int offr, int shCount)
9131 {
9132     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9133
9134     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9135     /* shift left accumulator */
9136     AccLsh(shCount, 1);
9137     /* or with result */
9138     /* back to result */
9139     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9140 }
9141
9142 /*-----------------------------------------------------------------*/
9143 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9144 /*-----------------------------------------------------------------*/
9145 static void shiftRLeftOrResult (operand *left, int offl,
9146                                 operand *result, int offr, int shCount)
9147 {
9148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9149     
9150     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9151     /* shift right accumulator */
9152     AccRsh(shCount, 1);
9153     /* or with result */
9154     /* back to result */
9155     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9156 }
9157
9158 /*-----------------------------------------------------------------*/
9159 /* genlshOne - left shift a one byte quantity by known count       */
9160 /*-----------------------------------------------------------------*/
9161 static void genlshOne (operand *result, operand *left, int shCount)
9162 {       
9163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9164     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9165 }
9166
9167 /*-----------------------------------------------------------------*/
9168 /* genlshTwo - left shift two bytes by known amount != 0           */
9169 /*-----------------------------------------------------------------*/
9170 static void genlshTwo (operand *result,operand *left, int shCount)
9171 {
9172     int size;
9173     
9174     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9175     size = pic16_getDataSize(result);
9176
9177     /* if shCount >= 8 */
9178     if (shCount >= 8) {
9179         shCount -= 8 ;
9180
9181         if (size > 1){
9182             if (shCount)
9183                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9184             else 
9185                 movLeft2Result(left, LSB, result, MSB16);
9186         }
9187         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9188     }
9189
9190     /*  1 <= shCount <= 7 */
9191     else {  
9192         if(size == 1)
9193             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9194         else 
9195             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9196     }
9197 }
9198
9199 /*-----------------------------------------------------------------*/
9200 /* shiftLLong - shift left one long from left to result            */
9201 /* offr = LSB or MSB16                                             */
9202 /*-----------------------------------------------------------------*/
9203 static void shiftLLong (operand *left, operand *result, int offr )
9204 {
9205     int size = AOP_SIZE(result);
9206     int same = pic16_sameRegs(AOP(left),AOP(result));
9207         int i;
9208
9209     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9210
9211         if (same && (offr == MSB16)) { //shift one byte
9212                 for(i=size-1;i>=MSB16;i--) {
9213                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9214                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9215                 }
9216         } else {
9217                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9218         }
9219         
9220     if (size > LSB+offr ){
9221                 if (same) {
9222                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9223                 } else {
9224                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9225                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9226                 }
9227          }
9228
9229     if(size > MSB16+offr){
9230                 if (same) {
9231                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9232                 } else {
9233                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9234                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9235                 }
9236     }
9237
9238     if(size > MSB24+offr){
9239                 if (same) {
9240                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9241                 } else {
9242                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9243                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9244                 }
9245     }
9246
9247     if(size > MSB32+offr){
9248                 if (same) {
9249                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9250                 } else {
9251                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9252                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9253                 }
9254     }
9255     if(offr != LSB)
9256                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9257
9258 }
9259
9260 /*-----------------------------------------------------------------*/
9261 /* genlshFour - shift four byte by a known amount != 0             */
9262 /*-----------------------------------------------------------------*/
9263 static void genlshFour (operand *result, operand *left, int shCount)
9264 {
9265     int size;
9266
9267     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9268     size = AOP_SIZE(result);
9269
9270     /* if shifting more that 3 bytes */
9271     if (shCount >= 24 ) {
9272         shCount -= 24;
9273         if (shCount)
9274             /* lowest order of left goes to the highest
9275             order of the destination */
9276             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9277         else
9278             movLeft2Result(left, LSB, result, MSB32);
9279
9280                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9281                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9282                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9283
9284         return;
9285     }
9286
9287     /* more than two bytes */
9288     else if ( shCount >= 16 ) {
9289         /* lower order two bytes goes to higher order two bytes */
9290         shCount -= 16;
9291         /* if some more remaining */
9292         if (shCount)
9293             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9294         else {
9295             movLeft2Result(left, MSB16, result, MSB32);
9296             movLeft2Result(left, LSB, result, MSB24);
9297         }
9298                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9299                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9300         return;
9301     }    
9302
9303     /* if more than 1 byte */
9304     else if ( shCount >= 8 ) {
9305         /* lower order three bytes goes to higher order  three bytes */
9306         shCount -= 8;
9307         if(size == 2){
9308             if(shCount)
9309                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9310             else
9311                 movLeft2Result(left, LSB, result, MSB16);
9312         }
9313         else{   /* size = 4 */
9314             if(shCount == 0){
9315                 movLeft2Result(left, MSB24, result, MSB32);
9316                 movLeft2Result(left, MSB16, result, MSB24);
9317                 movLeft2Result(left, LSB, result, MSB16);
9318                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9319             }
9320             else if(shCount == 1)
9321                 shiftLLong(left, result, MSB16);
9322             else{
9323                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9324                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9325                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9326                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9327             }
9328         }
9329     }
9330
9331     /* 1 <= shCount <= 7 */
9332     else if(shCount <= 3)
9333     { 
9334         shiftLLong(left, result, LSB);
9335         while(--shCount >= 1)
9336             shiftLLong(result, result, LSB);
9337     }
9338     /* 3 <= shCount <= 7, optimize */
9339     else{
9340         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9341         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9342         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9343     }
9344 }
9345
9346 /*-----------------------------------------------------------------*/
9347 /* genLeftShiftLiteral - left shifting by known count              */
9348 /*-----------------------------------------------------------------*/
9349 void pic16_genLeftShiftLiteral (operand *left,
9350                                  operand *right,
9351                                  operand *result,
9352                                  iCode *ic)
9353 {    
9354     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9355     int size;
9356
9357     FENTRY;
9358     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9359     pic16_freeAsmop(right,NULL,ic,TRUE);
9360
9361     pic16_aopOp(left,ic,FALSE);
9362     pic16_aopOp(result,ic,TRUE);
9363
9364     size = getSize(operandType(result));
9365
9366 #if VIEW_SIZE
9367     pic16_emitcode("; shift left ","result %d, left %d",size,
9368              AOP_SIZE(left));
9369 #endif
9370
9371     /* I suppose that the left size >= result size */
9372     if(shCount == 0){
9373         while(size--){
9374             movLeft2Result(left, size, result, size);
9375         }
9376     }
9377
9378     else if(shCount >= (size * 8))
9379         while(size--)
9380             pic16_aopPut(AOP(result),zero,size);
9381     else{
9382         switch (size) {
9383             case 1:
9384                 genlshOne (result,left,shCount);
9385                 break;
9386
9387             case 2:
9388             case 3:
9389                 genlshTwo (result,left,shCount);
9390                 break;
9391
9392             case 4:
9393                 genlshFour (result,left,shCount);
9394                 break;
9395         }
9396     }
9397     pic16_freeAsmop(left,NULL,ic,TRUE);
9398     pic16_freeAsmop(result,NULL,ic,TRUE);
9399 }
9400
9401 /*-----------------------------------------------------------------*
9402  * genMultiAsm - repeat assembly instruction for size of register.
9403  * if endian == 1, then the high byte (i.e base address + size of 
9404  * register) is used first else the low byte is used first;
9405  *-----------------------------------------------------------------*/
9406 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9407 {
9408
9409   int offset = 0;
9410
9411   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9412
9413   if(!reg)
9414     return;
9415
9416   if(!endian) {
9417     endian = 1;
9418   } else {
9419     endian = -1;
9420     offset = size-1;
9421   }
9422
9423   while(size--) {
9424     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9425     offset += endian;
9426   }
9427
9428 }
9429
9430 #if !(USE_GENERIC_SIGNED_SHIFT)
9431 /*-----------------------------------------------------------------*/
9432 /* genLeftShift - generates code for left shifting                 */
9433 /*-----------------------------------------------------------------*/
9434 static void genLeftShift (iCode *ic)
9435 {
9436   operand *left,*right, *result;
9437   int size, offset;
9438 //  char *l;
9439   symbol *tlbl , *tlbl1;
9440   pCodeOp *pctemp;
9441
9442   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9443
9444   right = IC_RIGHT(ic);
9445   left  = IC_LEFT(ic);
9446   result = IC_RESULT(ic);
9447
9448   pic16_aopOp(right,ic,FALSE);
9449
9450   /* if the shift count is known then do it 
9451      as efficiently as possible */
9452   if (AOP_TYPE(right) == AOP_LIT) {
9453     pic16_genLeftShiftLiteral (left,right,result,ic);
9454     return ;
9455   }
9456
9457   /* shift count is unknown then we have to form
9458    * a loop. Get the loop count in WREG : Note: we take
9459    * only the lower order byte since shifting
9460    * more than 32 bits make no sense anyway, ( the
9461    * largest size of an object can be only 32 bits ) */
9462   
9463   pic16_aopOp(left,ic,FALSE);
9464   pic16_aopOp(result,ic,FALSE);
9465
9466   /* now move the left to the result if they are not the
9467    * same, and if size > 1,
9468    * and if right is not same to result (!!!) -- VR */
9469   if (!pic16_sameRegs(AOP(left),AOP(result))
9470       && (AOP_SIZE(result) > 1)) {
9471
9472     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9473
9474     size = AOP_SIZE(result);
9475     offset=0;
9476     while (size--) {
9477
9478 #if 0
9479       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9480       if (*l == '@' && (IS_AOP_PREG(result))) {
9481
9482           pic16_emitcode("mov","a,%s",l);
9483           pic16_aopPut(AOP(result),"a",offset);
9484       } else
9485 #endif
9486       {
9487         /* we don't know if left is a literal or a register, take care -- VR */
9488         pic16_mov2f(AOP(result), AOP(left), offset);
9489       }
9490       offset++;
9491     }
9492   }
9493
9494   size = AOP_SIZE(result);
9495
9496   /* if it is only one byte then */
9497   if (size == 1) {
9498     if(optimized_for_speed) {
9499       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9500       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9501       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9502       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9503       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9504       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9505       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9506       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9507       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9508       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9509       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9510       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9511     } else {
9512
9513       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9514
9515       tlbl = newiTempLabel(NULL);
9516
9517 #if 1
9518       /* this is already done, why change it? */
9519       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9520                 pic16_mov2f(AOP(result), AOP(left), 0);
9521       }
9522 #endif
9523
9524       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9525       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9526       pic16_emitpLabel(tlbl->key);
9527       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9528       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9529       emitSKPC;
9530       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9531     }
9532     goto release ;
9533   }
9534     
9535   if (pic16_sameRegs(AOP(left),AOP(result))) {
9536
9537     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9538     
9539     tlbl = newiTempLabel(NULL);
9540     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9541     genMultiAsm(POC_RRCF, result, size,1);
9542     pic16_emitpLabel(tlbl->key);
9543     genMultiAsm(POC_RLCF, result, size,0);
9544     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9545     emitSKPC;
9546     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9547     goto release;
9548   }
9549
9550   //tlbl = newiTempLabel(NULL);
9551   //offset = 0 ;   
9552   //tlbl1 = newiTempLabel(NULL);
9553
9554   //reAdjustPreg(AOP(result));    
9555     
9556   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9557   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9558   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9559   //MOVA(l);
9560   //pic16_emitcode("add","a,acc");         
9561   //pic16_aopPut(AOP(result),"a",offset++);
9562   //while (--size) {
9563   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9564   //  MOVA(l);
9565   //  pic16_emitcode("rlc","a");         
9566   //  pic16_aopPut(AOP(result),"a",offset++);
9567   //}
9568   //reAdjustPreg(AOP(result));
9569
9570   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9571   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9572
9573
9574   tlbl = newiTempLabel(NULL);
9575   tlbl1= newiTempLabel(NULL);
9576
9577   size = AOP_SIZE(result);
9578   offset = 1;
9579
9580   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9581
9582   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9583
9584   /* offset should be 0, 1 or 3 */
9585   
9586   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9587   emitSKPNZ;
9588   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9589
9590   pic16_emitpcode(POC_MOVWF, pctemp);
9591
9592
9593   pic16_emitpLabel(tlbl->key);
9594
9595   emitCLRC;
9596   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9597   while(--size)
9598     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9599
9600   pic16_emitpcode(POC_DECFSZ,  pctemp);
9601   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602   pic16_emitpLabel(tlbl1->key);
9603
9604   pic16_popReleaseTempReg(pctemp,1);
9605
9606
9607  release:
9608   pic16_freeAsmop (right,NULL,ic,TRUE);
9609   pic16_freeAsmop(left,NULL,ic,TRUE);
9610   pic16_freeAsmop(result,NULL,ic,TRUE);
9611 }
9612 #endif
9613
9614
9615 #if 0
9616 #error old code (left here for reference)
9617 /*-----------------------------------------------------------------*/
9618 /* genLeftShift - generates code for left shifting                 */
9619 /*-----------------------------------------------------------------*/
9620 static void genLeftShift (iCode *ic)
9621 {
9622   operand *left,*right, *result;
9623   int size, offset;
9624   char *l;
9625   symbol *tlbl , *tlbl1;
9626   pCodeOp *pctemp;
9627
9628   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9629
9630   right = IC_RIGHT(ic);
9631   left  = IC_LEFT(ic);
9632   result = IC_RESULT(ic);
9633
9634   pic16_aopOp(right,ic,FALSE);
9635
9636   /* if the shift count is known then do it 
9637      as efficiently as possible */
9638   if (AOP_TYPE(right) == AOP_LIT) {
9639     pic16_genLeftShiftLiteral (left,right,result,ic);
9640     return ;
9641   }
9642
9643   /* shift count is unknown then we have to form 
9644      a loop get the loop count in B : Note: we take
9645      only the lower order byte since shifting
9646      more that 32 bits make no sense anyway, ( the
9647      largest size of an object can be only 32 bits ) */  
9648
9649     
9650   pic16_aopOp(left,ic,FALSE);
9651   pic16_aopOp(result,ic,FALSE);
9652
9653   /* now move the left to the result if they are not the
9654      same */
9655   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9656       AOP_SIZE(result) > 1) {
9657
9658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9659
9660     size = AOP_SIZE(result);
9661     offset=0;
9662     while (size--) {
9663       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9664       if (*l == '@' && (IS_AOP_PREG(result))) {
9665
9666         pic16_emitcode("mov","a,%s",l);
9667         pic16_aopPut(AOP(result),"a",offset);
9668       } else {
9669
9670         /* we don't know if left is a literal or a register, take care -- VR */
9671         pic16_mov2f(AOP(result), AOP(left), offset);
9672       }
9673       offset++;
9674     }
9675   }
9676
9677   size = AOP_SIZE(result);
9678
9679   /* if it is only one byte then */
9680   if (size == 1) {
9681     if(optimized_for_speed) {
9682       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9683       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9684       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9685       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9686       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9687       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9688       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9689       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9690       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9691       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9692       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9693       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9694     } else {
9695
9696       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9697
9698       tlbl = newiTempLabel(NULL);
9699       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9700                 pic16_mov2f(AOP(result), AOP(left), 0);
9701                 
9702 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9703 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9704       }
9705
9706       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9707       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9708       pic16_emitpLabel(tlbl->key);
9709       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9710       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9711       emitSKPC;
9712       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9713     }
9714     goto release ;
9715   }
9716     
9717   if (pic16_sameRegs(AOP(left),AOP(result))) {
9718
9719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9720     
9721     tlbl = newiTempLabel(NULL);
9722     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9723     genMultiAsm(POC_RRCF, result, size,1);
9724     pic16_emitpLabel(tlbl->key);
9725     genMultiAsm(POC_RLCF, result, size,0);
9726     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9727     emitSKPC;
9728     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9729     goto release;
9730   }
9731
9732   //tlbl = newiTempLabel(NULL);
9733   //offset = 0 ;   
9734   //tlbl1 = newiTempLabel(NULL);
9735
9736   //reAdjustPreg(AOP(result));    
9737     
9738   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9739   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9740   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9741   //MOVA(l);
9742   //pic16_emitcode("add","a,acc");         
9743   //pic16_aopPut(AOP(result),"a",offset++);
9744   //while (--size) {
9745   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9746   //  MOVA(l);
9747   //  pic16_emitcode("rlc","a");         
9748   //  pic16_aopPut(AOP(result),"a",offset++);
9749   //}
9750   //reAdjustPreg(AOP(result));
9751
9752   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9753   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9754
9755
9756   tlbl = newiTempLabel(NULL);
9757   tlbl1= newiTempLabel(NULL);
9758
9759   size = AOP_SIZE(result);
9760   offset = 1;
9761
9762   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9763
9764   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9765
9766   /* offset should be 0, 1 or 3 */
9767   
9768   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9769   emitSKPNZ;
9770   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9771
9772   pic16_emitpcode(POC_MOVWF, pctemp);
9773
9774
9775   pic16_emitpLabel(tlbl->key);
9776
9777   emitCLRC;
9778   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9779   while(--size)
9780     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9781
9782   pic16_emitpcode(POC_DECFSZ,  pctemp);
9783   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784   pic16_emitpLabel(tlbl1->key);
9785
9786   pic16_popReleaseTempReg(pctemp,1);
9787
9788
9789  release:
9790   pic16_freeAsmop (right,NULL,ic,TRUE);
9791   pic16_freeAsmop(left,NULL,ic,TRUE);
9792   pic16_freeAsmop(result,NULL,ic,TRUE);
9793 }
9794 #endif
9795
9796 /*-----------------------------------------------------------------*/
9797 /* genrshOne - right shift a one byte quantity by known count      */
9798 /*-----------------------------------------------------------------*/
9799 static void genrshOne (operand *result, operand *left,
9800                        int shCount, int sign)
9801 {
9802     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9803     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9804 }
9805
9806 /*-----------------------------------------------------------------*/
9807 /* genrshTwo - right shift two bytes by known amount != 0          */
9808 /*-----------------------------------------------------------------*/
9809 static void genrshTwo (operand *result,operand *left,
9810                        int shCount, int sign)
9811 {
9812   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9813   /* if shCount >= 8 */
9814   if (shCount >= 8) {
9815     shCount -= 8 ;
9816     if (shCount)
9817       shiftR1Left2Result(left, MSB16, result, LSB,
9818                          shCount, sign);
9819     else
9820       movLeft2Result(left, MSB16, result, LSB);
9821
9822     pic16_addSign (result, 1, sign);
9823   }
9824
9825   /*  1 <= shCount <= 7 */
9826   else
9827     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9828 }
9829
9830 /*-----------------------------------------------------------------*/
9831 /* shiftRLong - shift right one long from left to result           */
9832 /* offl = LSB or MSB16                                             */
9833 /*-----------------------------------------------------------------*/
9834 static void shiftRLong (operand *left, int offl,
9835                         operand *result, int sign)
9836 {
9837     int size = AOP_SIZE(result);
9838     int same = pic16_sameRegs(AOP(left),AOP(result));
9839     int i;
9840     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9841
9842         if (same && (offl == MSB16)) { //shift one byte right
9843                 for(i=MSB16;i<size;i++) {
9844                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9845                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9846                 }
9847         }
9848
9849     if(sign)
9850                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9851         else
9852                 emitCLRC;
9853
9854         if (same) {
9855                 if (offl == LSB)
9856                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9857         } else {
9858         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9859         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9860         }
9861
9862     if(offl == MSB16) {
9863         /* add sign of "a" */
9864         pic16_addSign(result, MSB32, sign);
9865         }
9866
9867         if (same) {
9868         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9869         } else {
9870         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9871         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9872         }
9873         
9874         if (same) {
9875         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9876         } else {
9877         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9878         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9879         }
9880
9881         if (same) {
9882         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9883         } else {
9884         if(offl == LSB){
9885                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9886                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9887         }
9888         }
9889 }
9890
9891 /*-----------------------------------------------------------------*/
9892 /* genrshFour - shift four byte by a known amount != 0             */
9893 /*-----------------------------------------------------------------*/
9894 static void genrshFour (operand *result, operand *left,
9895                         int shCount, int sign)
9896 {
9897   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9898   /* if shifting more that 3 bytes */
9899   if(shCount >= 24 ) {
9900     shCount -= 24;
9901     if(shCount)
9902       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9903     else
9904       movLeft2Result(left, MSB32, result, LSB);
9905
9906     pic16_addSign(result, MSB16, sign);
9907   }
9908   else if(shCount >= 16){
9909     shCount -= 16;
9910     if(shCount)
9911       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9912     else{
9913       movLeft2Result(left, MSB24, result, LSB);
9914       movLeft2Result(left, MSB32, result, MSB16);
9915     }
9916     pic16_addSign(result, MSB24, sign);
9917   }
9918   else if(shCount >= 8){
9919     shCount -= 8;
9920     if(shCount == 1)
9921       shiftRLong(left, MSB16, result, sign);
9922     else if(shCount == 0){
9923       movLeft2Result(left, MSB16, result, LSB);
9924       movLeft2Result(left, MSB24, result, MSB16);
9925       movLeft2Result(left, MSB32, result, MSB24);
9926       pic16_addSign(result, MSB32, sign);
9927     }
9928     else{ //shcount >= 2
9929       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9930       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9931       /* the last shift is signed */
9932       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9933       pic16_addSign(result, MSB32, sign);
9934     }
9935   }
9936   else{   /* 1 <= shCount <= 7 */
9937     if(shCount <= 2){
9938       shiftRLong(left, LSB, result, sign);
9939       if(shCount == 2)
9940         shiftRLong(result, LSB, result, sign);
9941     }
9942     else{
9943       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9944       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9945       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9946     }
9947   }
9948 }
9949
9950 /*-----------------------------------------------------------------*/
9951 /* genRightShiftLiteral - right shifting by known count            */
9952 /*-----------------------------------------------------------------*/
9953 static void genRightShiftLiteral (operand *left,
9954                                   operand *right,
9955                                   operand *result,
9956                                   iCode *ic,
9957                                   int sign)
9958 {    
9959   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9960   int lsize,res_size;
9961
9962   pic16_freeAsmop(right,NULL,ic,TRUE);
9963
9964   pic16_aopOp(left,ic,FALSE);
9965   pic16_aopOp(result,ic,TRUE);
9966
9967   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9968
9969 #if VIEW_SIZE
9970   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9971                  AOP_SIZE(left));
9972 #endif
9973
9974   lsize = pic16_getDataSize(left);
9975   res_size = pic16_getDataSize(result);
9976   /* test the LEFT size !!! */
9977
9978   /* I suppose that the left size >= result size */
9979   if(shCount == 0){
9980     assert (res_size <= lsize);
9981     while (res_size--) {
9982       pic16_mov2f (AOP(result), AOP(left), res_size);
9983     } // for
9984   }
9985
9986   else if(shCount >= (lsize * 8)){
9987
9988     if(res_size == 1) {
9989       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9990       if(sign) {
9991         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9992         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9993       }
9994     } else {
9995
9996       if(sign) {
9997         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9998         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9999         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10000         while(res_size--)
10001           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10002
10003       } else {
10004
10005         while(res_size--)
10006           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10007       }
10008     }
10009   } else {
10010
10011     switch (res_size) {
10012     case 1:
10013       genrshOne (result,left,shCount,sign);
10014       break;
10015
10016     case 2:
10017       genrshTwo (result,left,shCount,sign);
10018       break;
10019
10020     case 4:
10021       genrshFour (result,left,shCount,sign);
10022       break;
10023     default :
10024       break;
10025     }
10026
10027   }
10028
10029   pic16_freeAsmop(left,NULL,ic,TRUE);
10030   pic16_freeAsmop(result,NULL,ic,TRUE);
10031 }
10032
10033 #if !(USE_GENERIC_SIGNED_SHIFT)
10034 /*-----------------------------------------------------------------*/
10035 /* genSignedRightShift - right shift of signed number              */
10036 /*-----------------------------------------------------------------*/
10037 static void genSignedRightShift (iCode *ic)
10038 {
10039   operand *right, *left, *result;
10040   int size, offset;
10041   //  char *l;
10042   symbol *tlbl, *tlbl1 ;
10043   pCodeOp *pctemp;
10044
10045   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10046
10047   /* we do it the hard way put the shift count in b
10048      and loop thru preserving the sign */
10049   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10050
10051   right = IC_RIGHT(ic);
10052   left  = IC_LEFT(ic);
10053   result = IC_RESULT(ic);
10054
10055   pic16_aopOp(right,ic,FALSE);  
10056   pic16_aopOp(left,ic,FALSE);
10057   pic16_aopOp(result,ic,FALSE);
10058
10059
10060   if ( AOP_TYPE(right) == AOP_LIT) {
10061     genRightShiftLiteral (left,right,result,ic,1);
10062     return ;
10063   }
10064   /* shift count is unknown then we have to form 
10065      a loop get the loop count in B : Note: we take
10066      only the lower order byte since shifting
10067      more that 32 bits make no sense anyway, ( the
10068      largest size of an object can be only 32 bits ) */  
10069
10070   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10071   //pic16_emitcode("inc","b");
10072   //pic16_freeAsmop (right,NULL,ic,TRUE);
10073   //pic16_aopOp(left,ic,FALSE);
10074   //pic16_aopOp(result,ic,FALSE);
10075
10076   /* now move the left to the result if they are not the
10077      same */
10078   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10079       AOP_SIZE(result) > 1) {
10080
10081     size = AOP_SIZE(result);
10082     offset=0;
10083     while (size--) { 
10084       /*
10085         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10086         if (*l == '@' && IS_AOP_PREG(result)) {
10087
10088         pic16_emitcode("mov","a,%s",l);
10089         pic16_aopPut(AOP(result),"a",offset);
10090         } else
10091         pic16_aopPut(AOP(result),l,offset);
10092       */
10093       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10094       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10095
10096       offset++;
10097     }
10098   }
10099
10100   /* mov the highest order bit to OVR */    
10101   tlbl = newiTempLabel(NULL);
10102   tlbl1= newiTempLabel(NULL);
10103
10104   size = AOP_SIZE(result);
10105   offset = size - 1;
10106
10107   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10108
10109   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10110
10111   /* offset should be 0, 1 or 3 */
10112   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10113   emitSKPNZ;
10114   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10115
10116   pic16_emitpcode(POC_MOVWF, pctemp);
10117
10118
10119   pic16_emitpLabel(tlbl->key);
10120
10121   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10122   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10123
10124   while(--size) {
10125     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10126   }
10127
10128   pic16_emitpcode(POC_DECFSZ,  pctemp);
10129   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10130   pic16_emitpLabel(tlbl1->key);
10131
10132   pic16_popReleaseTempReg(pctemp,1);
10133 #if 0
10134   size = AOP_SIZE(result);
10135   offset = size - 1;
10136   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10137   pic16_emitcode("rlc","a");
10138   pic16_emitcode("mov","ov,c");
10139   /* if it is only one byte then */
10140   if (size == 1) {
10141     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10142     MOVA(l);
10143     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10144     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10145     pic16_emitcode("mov","c,ov");
10146     pic16_emitcode("rrc","a");
10147     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10148     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10149     pic16_aopPut(AOP(result),"a",0);
10150     goto release ;
10151   }
10152
10153   reAdjustPreg(AOP(result));
10154   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10155   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10156   pic16_emitcode("mov","c,ov");
10157   while (size--) {
10158     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10159     MOVA(l);
10160     pic16_emitcode("rrc","a");         
10161     pic16_aopPut(AOP(result),"a",offset--);
10162   }
10163   reAdjustPreg(AOP(result));
10164   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10165   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10166
10167  release:
10168 #endif
10169
10170   pic16_freeAsmop(left,NULL,ic,TRUE);
10171   pic16_freeAsmop(result,NULL,ic,TRUE);
10172   pic16_freeAsmop(right,NULL,ic,TRUE);
10173 }
10174 #endif
10175
10176 #if !(USE_GENERIC_SIGNED_SHIFT)
10177 #warning This implementation of genRightShift() is incomplete!
10178 /*-----------------------------------------------------------------*/
10179 /* genRightShift - generate code for right shifting                */
10180 /*-----------------------------------------------------------------*/
10181 static void genRightShift (iCode *ic)
10182 {
10183     operand *right, *left, *result;
10184     sym_link *letype ;
10185     int size, offset;
10186     char *l;
10187     symbol *tlbl, *tlbl1 ;
10188
10189     /* if signed then we do it the hard way preserve the
10190     sign bit moving it inwards */
10191     letype = getSpec(operandType(IC_LEFT(ic)));
10192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10193
10194     if (!SPEC_USIGN(letype)) {
10195         genSignedRightShift (ic);
10196         return ;
10197     }
10198
10199     /* signed & unsigned types are treated the same : i.e. the
10200     signed is NOT propagated inwards : quoting from the
10201     ANSI - standard : "for E1 >> E2, is equivalent to division
10202     by 2**E2 if unsigned or if it has a non-negative value,
10203     otherwise the result is implementation defined ", MY definition
10204     is that the sign does not get propagated */
10205
10206     right = IC_RIGHT(ic);
10207     left  = IC_LEFT(ic);
10208     result = IC_RESULT(ic);
10209
10210     pic16_aopOp(right,ic,FALSE);
10211
10212     /* if the shift count is known then do it 
10213     as efficiently as possible */
10214     if (AOP_TYPE(right) == AOP_LIT) {
10215         genRightShiftLiteral (left,right,result,ic, 0);
10216         return ;
10217     }
10218
10219     /* shift count is unknown then we have to form 
10220     a loop get the loop count in B : Note: we take
10221     only the lower order byte since shifting
10222     more that 32 bits make no sense anyway, ( the
10223     largest size of an object can be only 32 bits ) */  
10224
10225     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10226     pic16_emitcode("inc","b");
10227     pic16_aopOp(left,ic,FALSE);
10228     pic16_aopOp(result,ic,FALSE);
10229
10230     /* now move the left to the result if they are not the
10231     same */
10232     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10233         AOP_SIZE(result) > 1) {
10234
10235         size = AOP_SIZE(result);
10236         offset=0;
10237         while (size--) {
10238             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10239             if (*l == '@' && IS_AOP_PREG(result)) {
10240
10241                 pic16_emitcode("mov","a,%s",l);
10242                 pic16_aopPut(AOP(result),"a",offset);
10243             } else
10244                 pic16_aopPut(AOP(result),l,offset);
10245             offset++;
10246         }
10247     }
10248
10249     tlbl = newiTempLabel(NULL);
10250     tlbl1= newiTempLabel(NULL);
10251     size = AOP_SIZE(result);
10252     offset = size - 1;
10253
10254     /* if it is only one byte then */
10255     if (size == 1) {
10256
10257       tlbl = newiTempLabel(NULL);
10258       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10259         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10260         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10261       }
10262
10263       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10264       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10265       pic16_emitpLabel(tlbl->key);
10266       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10267       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10268       emitSKPC;
10269       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10270
10271       goto release ;
10272     }
10273
10274     reAdjustPreg(AOP(result));
10275     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10276     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10277     CLRC;
10278     while (size--) {
10279         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10280         MOVA(l);
10281         pic16_emitcode("rrc","a");         
10282         pic16_aopPut(AOP(result),"a",offset--);
10283     }
10284     reAdjustPreg(AOP(result));
10285
10286     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10287     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10288
10289 release:
10290     pic16_freeAsmop(left,NULL,ic,TRUE);
10291     pic16_freeAsmop (right,NULL,ic,TRUE);
10292     pic16_freeAsmop(result,NULL,ic,TRUE);
10293 }
10294 #endif
10295
10296 #if (USE_GENERIC_SIGNED_SHIFT)
10297 /*-----------------------------------------------------------------*/
10298 /* genGenericShift - generates code for left or right shifting     */
10299 /*-----------------------------------------------------------------*/
10300 static void genGenericShift (iCode *ic, int isShiftLeft) {
10301   operand *left,*right, *result;
10302   int offset;
10303   int sign, signedCount;
10304   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10305   PIC_OPCODE pos_shift, neg_shift;
10306
10307   FENTRY;
10308
10309   right = IC_RIGHT(ic);
10310   left  = IC_LEFT(ic);
10311   result = IC_RESULT(ic);
10312
10313   pic16_aopOp(right,ic,FALSE);
10314   pic16_aopOp(left,ic,FALSE);
10315   pic16_aopOp(result,ic,TRUE);
10316
10317   sign = !SPEC_USIGN(operandType (left));
10318   signedCount = !SPEC_USIGN(operandType (right));
10319
10320   /* if the shift count is known then do it 
10321      as efficiently as possible */
10322   if (AOP_TYPE(right) == AOP_LIT) {
10323     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10324     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10325     // we should modify right->aopu.aop_lit here!
10326     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10327     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10328     if (isShiftLeft)
10329       pic16_genLeftShiftLiteral (left,right,result,ic);
10330     else
10331       genRightShiftLiteral (left,right,result,ic, sign);
10332
10333     goto release;
10334   } // if (right is literal)
10335
10336   /* shift count is unknown then we have to form a loop.
10337    * Note: we take only the lower order byte since shifting
10338    * more than 32 bits make no sense anyway, ( the
10339    * largest size of an object can be only 32 bits )
10340    * Note: we perform arithmetic shifts if the left operand is
10341    * signed and we do an (effective) right shift, i. e. we
10342    * shift in the sign bit from the left. */
10343    
10344   label_complete = newiTempLabel ( NULL );
10345   label_loop_pos = newiTempLabel ( NULL );
10346   label_loop_neg = NULL;
10347   label_negative = NULL;
10348   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10349   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10350
10351   if (signedCount) {
10352     // additional labels needed
10353     label_loop_neg = newiTempLabel ( NULL );
10354     label_negative = newiTempLabel ( NULL );
10355   } // if
10356
10357   // copy source to result -- this will effectively truncate the left operand to the size of result!
10358   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10359   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10360   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10361     pic16_mov2f (AOP(result),AOP(left), offset);
10362   } // for
10363
10364   // if result is longer than left, fill with zeros (or sign)
10365   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10366     if (sign && AOP_SIZE(left) > 0) {
10367       // shift signed operand -- fill with sign
10368       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10369       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10370       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10371       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10372         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10373       } // for
10374     } else {
10375       // shift unsigned operand -- fill result with zeros
10376       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10377         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10378       } // for
10379     }
10380   } // if (size mismatch)
10381
10382   pic16_mov2w (AOP(right), 0);
10383   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10384   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10385   
10386 #if 0
10387   // perform a shift by one (shift count is positive)
10388   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10389   // 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])
10390   pic16_emitpLabel (label_loop_pos->key);
10391   emitCLRC;
10392   if (sign && (pos_shift == POC_RRCF)) {
10393     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10394     emitSETC;
10395   } // if
10396   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10397   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10398   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10399 #else
10400   // perform a shift by one (shift count is positive)
10401   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10402   // 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])
10403   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10404   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10405   emitCLRC;
10406   pic16_emitpLabel (label_loop_pos->key);
10407   if (sign && (pos_shift == POC_RRCF)) {
10408     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10409     emitSETC;
10410   } // if
10411   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10412   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10413   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10414   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10415 #endif
10416
10417   if (signedCount) {
10418     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10419
10420     pic16_emitpLabel (label_negative->key);
10421     // perform a shift by -1 (shift count is negative)
10422     // 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)
10423     emitCLRC;
10424     pic16_emitpLabel (label_loop_neg->key);
10425     if (sign && (neg_shift == POC_RRCF)) {
10426       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10427       emitSETC;
10428     } // if
10429     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10430     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10431     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10432     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10433   } // if (signedCount)
10434
10435   pic16_emitpLabel (label_complete->key);
10436
10437 release:
10438   pic16_freeAsmop (right,NULL,ic,TRUE);
10439   pic16_freeAsmop(left,NULL,ic,TRUE);
10440   pic16_freeAsmop(result,NULL,ic,TRUE);
10441 }
10442
10443 static void genLeftShift (iCode *ic) {
10444   genGenericShift (ic, 1);
10445 }
10446
10447 static void genRightShift (iCode *ic) {
10448   genGenericShift (ic, 0);
10449 }
10450 #endif
10451
10452
10453 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10454 void pic16_loadFSR0(operand *op, int lit)
10455 {
10456   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10457     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10458   } else {
10459     assert (!OP_SYMBOL(op)->remat);
10460     // set up FSR0 with address of result
10461     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10462     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10463   }
10464 }
10465
10466 /*----------------------------------------------------------------*/
10467 /* pic16_derefPtr - move one byte from the location ptr points to */
10468 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10469 /*                  to the location ptr points to (doWrite != 0)   */
10470 /*----------------------------------------------------------------*/
10471 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10472 {
10473   if (!IS_PTR(operandType(ptr)))
10474   {
10475     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10476     else pic16_mov2w (AOP(ptr), 0);
10477     return;
10478   }
10479
10480   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10481   /* We might determine pointer type right here: */
10482   p_type = DCL_TYPE(operandType(ptr));
10483
10484   switch (p_type) {
10485     case FPOINTER:
10486     case POINTER:
10487       if (!fsr0_setup || !*fsr0_setup)
10488       {
10489         pic16_loadFSR0( ptr, 0 );
10490         if (fsr0_setup) *fsr0_setup = 1;
10491       }
10492       if (doWrite)
10493         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10494       else
10495         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10496       break;
10497
10498     case GPOINTER:
10499       if (AOP(ptr)->aopu.aop_reg[2]) {
10500         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10501         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10502         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10503         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10504         pic16_mov2w(AOP(ptr), 2);
10505         pic16_callGenericPointerRW(doWrite, 1);
10506       } else {
10507         // data pointer (just 2 byte given)
10508         if (!fsr0_setup || !*fsr0_setup)
10509         {
10510           pic16_loadFSR0( ptr, 0 );
10511           if (fsr0_setup) *fsr0_setup = 1;
10512         }
10513         if (doWrite)
10514           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10515         else
10516           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10517       }
10518       break;
10519
10520     default:
10521       assert (0 && "invalid pointer type specified");
10522       break;
10523   }
10524 }
10525
10526 /*-----------------------------------------------------------------*/
10527 /* genUnpackBits - generates code for unpacking bits               */
10528 /*-----------------------------------------------------------------*/
10529 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10530 {    
10531   int shCnt ;
10532   sym_link *etype, *letype;
10533   int blen=0, bstr=0;
10534   int lbstr;
10535   int same;
10536   pCodeOp *op;
10537
10538   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10539   etype = getSpec(operandType(result));
10540   letype = getSpec(operandType(left));
10541
10542   //    if(IS_BITFIELD(etype)) {
10543   blen = SPEC_BLEN(etype);
10544   bstr = SPEC_BSTR(etype);
10545   //    }
10546
10547   lbstr = SPEC_BSTR( letype );
10548
10549   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10550       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10551
10552 #if 1
10553   if((blen == 1) && (bstr < 8)
10554       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10555     /* it is a single bit, so use the appropriate bit instructions */
10556     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10557
10558     same = pic16_sameRegs(AOP(left),AOP(result));
10559     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10560     pic16_emitpcode(POC_CLRF, op);
10561
10562     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10563       /* workaround to reduce the extra lfsr instruction */
10564       pic16_emitpcode(POC_BTFSC,
10565           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10566     } else {
10567       assert (PIC_IS_DATA_PTR (operandType(left)));
10568       pic16_loadFSR0 (left, 0);
10569       pic16_emitpcode(POC_BTFSC,
10570           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10571     }
10572
10573     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10574       /* unsigned bitfields result in either 0 or 1 */
10575       pic16_emitpcode(POC_INCF, op);
10576     } else {
10577       /* signed bitfields result in either 0 or -1 */
10578       pic16_emitpcode(POC_DECF, op);
10579     }
10580     if (same) {
10581       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10582     }
10583
10584     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10585     return;
10586   }
10587
10588 #endif
10589
10590   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10591     // access symbol directly
10592     pic16_mov2w (AOP(left), 0);
10593   } else {
10594     pic16_derefPtr (left, ptype, 0, NULL);
10595   }
10596
10597   /* if we have bitdisplacement then it fits   */
10598   /* into this byte completely or if length is */
10599   /* less than a byte                          */
10600   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10601
10602     /* shift right acc */
10603     AccRsh(shCnt, 0);
10604
10605     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10606           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10607
10608     /* VR -- normally I would use the following, but since we use the hack,
10609      * to avoid the masking from AccRsh, why not mask it right now? */
10610
10611     /*
10612        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10613      */
10614
10615     /* extend signed bitfields to 8 bits */
10616     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10617     {
10618       assert (blen + bstr > 0);
10619       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10620       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10621     }
10622
10623     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10624
10625     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10626     return ;
10627   }
10628
10629   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10630   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10631   exit(-1);
10632
10633   return ;
10634 }
10635
10636
10637 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10638 {
10639   int size, offset = 0, leoffset=0 ;
10640
10641         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10642         pic16_aopOp(result, ic, TRUE);
10643
10644         FENTRY;
10645
10646         size = AOP_SIZE(result);
10647 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10648
10649
10650 #if 1
10651         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10652                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10653                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10654                 goto release;
10655         }
10656 #endif
10657
10658         if(AOP(left)->aopu.pcop->type == PO_DIR)
10659                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10660
10661         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10662
10663         while (size--) {
10664                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10665                 
10666 //              pic16_DumpOp("(result)",result);
10667                 if(is_LitAOp(AOP(result))) {
10668                         pic16_mov2w(AOP(left), offset); // patch 8
10669                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10670                 } else {
10671                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10672                                 pic16_popGet(AOP(left), offset), //patch 8
10673                                 pic16_popGet(AOP(result), offset)));
10674                 }
10675
10676                 offset++;
10677                 leoffset++;
10678         }
10679
10680 release:
10681     pic16_freeAsmop(result,NULL,ic,TRUE);
10682 }
10683
10684
10685
10686 /*-----------------------------------------------------------------*/
10687 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10688 /*-----------------------------------------------------------------*/
10689 static void genNearPointerGet (operand *left, 
10690                                operand *result, 
10691                                iCode *ic)
10692 {
10693 //  asmop *aop = NULL;
10694   //regs *preg = NULL ;
10695   sym_link *rtype, *retype;
10696   sym_link *ltype, *letype;
10697
10698     FENTRY;
10699     
10700     rtype = operandType(result);
10701     retype= getSpec(rtype);
10702     ltype = operandType(left);
10703     letype= getSpec(ltype);
10704     
10705     pic16_aopOp(left,ic,FALSE);
10706
10707 //    pic16_DumpOp("(left)",left);
10708 //    pic16_DumpOp("(result)",result);
10709
10710     /* if left is rematerialisable and
10711      * result is not bit variable type and
10712      * the left is pointer to data space i.e
10713      * lower 128 bytes of space */
10714     
10715     if (AOP_TYPE(left) == AOP_PCODE
10716       && !IS_BITFIELD(retype)
10717       && DCL_TYPE(ltype) == POINTER) {
10718
10719         genDataPointerGet (left,result,ic);
10720         pic16_freeAsmop(left, NULL, ic, TRUE);
10721         return ;
10722     }
10723     
10724     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10725     pic16_aopOp (result,ic,TRUE);
10726     
10727     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10728
10729 #if 1
10730     if(IS_BITFIELD( retype )
10731       && (SPEC_BLEN(operandType(result))==1)
10732     ) {
10733       iCode *nextic;
10734       pCodeOp *jop;
10735       int bitstrt, bytestrt;
10736
10737         /* if this is bitfield of size 1, see if we are checking the value
10738          * of a single bit in an if-statement,
10739          * if yes, then don't generate usual code, but execute the
10740          * genIfx directly -- VR */
10741
10742         nextic = ic->next;
10743
10744         /* CHECK: if next iCode is IFX
10745          * and current result operand is nextic's conditional operand
10746          * and current result operand live ranges ends at nextic's key number
10747          */
10748         if((nextic->op == IFX)
10749           && (result == IC_COND(nextic))
10750           && (OP_LIVETO(result) == nextic->seq)
10751           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10752           ) {
10753             /* everything is ok then */
10754             /* find a way to optimize the genIfx iCode */
10755
10756             bytestrt = SPEC_BSTR(operandType(result))/8;
10757             bitstrt = SPEC_BSTR(operandType(result))%8;
10758             
10759             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10760
10761             genIfxpCOpJump(nextic, jop);
10762             
10763             pic16_freeAsmop(left, NULL, ic, TRUE);
10764             pic16_freeAsmop(result, NULL, ic, TRUE);
10765             return;
10766         }
10767     }
10768 #endif
10769
10770     /* if bitfield then unpack the bits */
10771     if (IS_BITFIELD(letype)) 
10772       genUnpackBits (result, left, NULL, POINTER);
10773     else {
10774       /* we have can just get the values */
10775       int size = AOP_SIZE(result);
10776       int offset = 0;   
10777         
10778       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10779
10780       pic16_loadFSR0( left, 0 );
10781
10782       while(size--) {
10783         if(size) {
10784           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10785                 pic16_popGet(AOP(result), offset++)));
10786         } else {
10787           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10788                 pic16_popGet(AOP(result), offset++)));
10789         }
10790       }
10791     }
10792
10793 #if 0
10794     /* now some housekeeping stuff */
10795     if (aop) {
10796       /* we had to allocate for this iCode */
10797       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10798       pic16_freeAsmop(NULL,aop,ic,TRUE);
10799     } else { 
10800       /* we did not allocate which means left
10801        * already in a pointer register, then
10802        * if size > 0 && this could be used again
10803        * we have to point it back to where it 
10804        * belongs */
10805       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10806       if (AOP_SIZE(result) > 1
10807         && !OP_SYMBOL(left)->remat
10808         && ( OP_SYMBOL(left)->liveTo > ic->seq
10809             || ic->depth )) {
10810 //        int size = AOP_SIZE(result) - 1;
10811 //        while (size--)
10812 //          pic16_emitcode("dec","%s",rname);
10813         }
10814     }
10815 #endif
10816
10817     /* done */
10818     pic16_freeAsmop(left,NULL,ic,TRUE);
10819     pic16_freeAsmop(result,NULL,ic,TRUE);
10820 }
10821
10822 /*-----------------------------------------------------------------*/
10823 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10824 /*-----------------------------------------------------------------*/
10825 static void genPagedPointerGet (operand *left, 
10826                                operand *result, 
10827                                iCode *ic)
10828 {
10829     asmop *aop = NULL;
10830     regs *preg = NULL ;
10831     char *rname ;
10832     sym_link *rtype, *retype;    
10833
10834     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10835
10836     rtype = operandType(result);
10837     retype= getSpec(rtype);
10838     
10839     pic16_aopOp(left,ic,FALSE);
10840
10841   /* if the value is already in a pointer register
10842        then don't need anything more */
10843     if (!AOP_INPREG(AOP(left))) {
10844         /* otherwise get a free pointer register */
10845         aop = newAsmop(0);
10846         preg = getFreePtr(ic,&aop,FALSE);
10847         pic16_emitcode("mov","%s,%s",
10848                 preg->name,
10849                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10850         rname = preg->name ;
10851     } else
10852         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10853     
10854     pic16_freeAsmop(left,NULL,ic,TRUE);
10855     pic16_aopOp (result,ic,TRUE);
10856
10857     /* if bitfield then unpack the bits */
10858     if (IS_BITFIELD(retype)) 
10859         genUnpackBits (result,left,rname,PPOINTER);
10860     else {
10861         /* we have can just get the values */
10862         int size = AOP_SIZE(result);
10863         int offset = 0 ;        
10864         
10865         while (size--) {
10866             
10867             pic16_emitcode("movx","a,@%s",rname);
10868             pic16_aopPut(AOP(result),"a",offset);
10869             
10870             offset++ ;
10871             
10872             if (size)
10873                 pic16_emitcode("inc","%s",rname);
10874         }
10875     }
10876
10877     /* now some housekeeping stuff */
10878     if (aop) {
10879         /* we had to allocate for this iCode */
10880         pic16_freeAsmop(NULL,aop,ic,TRUE);
10881     } else { 
10882         /* we did not allocate which means left
10883            already in a pointer register, then
10884            if size > 0 && this could be used again
10885            we have to point it back to where it 
10886            belongs */
10887         if (AOP_SIZE(result) > 1 &&
10888             !OP_SYMBOL(left)->remat &&
10889             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10890               ic->depth )) {
10891             int size = AOP_SIZE(result) - 1;
10892             while (size--)
10893                 pic16_emitcode("dec","%s",rname);
10894         }
10895     }
10896
10897     /* done */
10898     pic16_freeAsmop(result,NULL,ic,TRUE);
10899     
10900         
10901 }
10902
10903 #if 0
10904 /* This code is not adjusted to PIC16 and fails utterly.
10905  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10906
10907 /*-----------------------------------------------------------------*/
10908 /* genFarPointerGet - gget value from far space                    */
10909 /*-----------------------------------------------------------------*/
10910 static void genFarPointerGet (operand *left,
10911                               operand *result, iCode *ic)
10912 {
10913     int size, offset ;
10914     sym_link *retype = getSpec(operandType(result));
10915
10916     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10917
10918     pic16_aopOp(left,ic,FALSE);
10919
10920     /* if the operand is already in dptr 
10921     then we do nothing else we move the value to dptr */
10922     if (AOP_TYPE(left) != AOP_STR) {
10923         /* if this is remateriazable */
10924         if (AOP_TYPE(left) == AOP_IMMD)
10925             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10926         else { /* we need to get it byte by byte */
10927             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10928             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10929             if (options.model == MODEL_FLAT24)
10930             {
10931                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10932             }
10933         }
10934     }
10935     /* so dptr know contains the address */
10936     pic16_freeAsmop(left,NULL,ic,TRUE);
10937     pic16_aopOp(result,ic,TRUE);
10938
10939     /* if bit then unpack */
10940     if (IS_BITFIELD(retype)) 
10941         genUnpackBits(result,left,"dptr",FPOINTER);
10942     else {
10943         size = AOP_SIZE(result);
10944         offset = 0 ;
10945
10946         while (size--) {
10947             pic16_emitcode("movx","a,@dptr");
10948             pic16_aopPut(AOP(result),"a",offset++);
10949             if (size)
10950                 pic16_emitcode("inc","dptr");
10951         }
10952     }
10953
10954     pic16_freeAsmop(result,NULL,ic,TRUE);
10955 }
10956 #endif
10957
10958 #if 0
10959 /*-----------------------------------------------------------------*/
10960 /* genCodePointerGet - get value from code space                  */
10961 /*-----------------------------------------------------------------*/
10962 static void genCodePointerGet (operand *left,
10963                                 operand *result, iCode *ic)
10964 {
10965     int size, offset ;
10966     sym_link *retype = getSpec(operandType(result));
10967
10968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10969
10970     pic16_aopOp(left,ic,FALSE);
10971
10972     /* if the operand is already in dptr 
10973     then we do nothing else we move the value to dptr */
10974     if (AOP_TYPE(left) != AOP_STR) {
10975         /* if this is remateriazable */
10976         if (AOP_TYPE(left) == AOP_IMMD)
10977             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10978         else { /* we need to get it byte by byte */
10979             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10980             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10981             if (options.model == MODEL_FLAT24)
10982             {
10983                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10984             }
10985         }
10986     }
10987     /* so dptr know contains the address */
10988     pic16_freeAsmop(left,NULL,ic,TRUE);
10989     pic16_aopOp(result,ic,FALSE);
10990
10991     /* if bit then unpack */
10992     if (IS_BITFIELD(retype)) 
10993         genUnpackBits(result,left,"dptr",CPOINTER);
10994     else {
10995         size = AOP_SIZE(result);
10996         offset = 0 ;
10997
10998         while (size--) {
10999             pic16_emitcode("clr","a");
11000             pic16_emitcode("movc","a,@a+dptr");
11001             pic16_aopPut(AOP(result),"a",offset++);
11002             if (size)
11003                 pic16_emitcode("inc","dptr");
11004         }
11005     }
11006
11007     pic16_freeAsmop(result,NULL,ic,TRUE);
11008 }
11009 #endif
11010
11011 #if 0
11012 /*-----------------------------------------------------------------*/
11013 /* genGenPointerGet - gget value from generic pointer space        */
11014 /*-----------------------------------------------------------------*/
11015 static void genGenPointerGet (operand *left,
11016                               operand *result, iCode *ic)
11017 {
11018   int size, offset, lit;
11019   sym_link *retype = getSpec(operandType(result));
11020
11021         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11022         pic16_aopOp(left,ic,FALSE);
11023         pic16_aopOp(result,ic,FALSE);
11024         size = AOP_SIZE(result);
11025
11026         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11027
11028         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11029
11030                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11031                 // load FSR0 from immediate
11032                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11033
11034 //              pic16_loadFSR0( left );
11035
11036                 offset = 0;
11037                 while(size--) {
11038                         if(size) {
11039                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11040                         } else {
11041                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11042                         }
11043                         offset++;
11044                 }
11045                 goto release;
11046
11047         }
11048         else { /* we need to get it byte by byte */
11049                 // set up FSR0 with address from left
11050                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11051                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11052                 
11053                 offset = 0 ;
11054
11055                 while(size--) {
11056                         if(size) {
11057                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11058                         } else {
11059                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11060                         }
11061                         offset++;
11062                 }
11063                 goto release;
11064         }
11065
11066   /* if bit then unpack */
11067         if (IS_BITFIELD(retype)) 
11068                 genUnpackBits(result,left,"BAD",GPOINTER);
11069
11070         release:
11071         pic16_freeAsmop(left,NULL,ic,TRUE);
11072         pic16_freeAsmop(result,NULL,ic,TRUE);
11073
11074 }
11075 #endif
11076
11077
11078 /*-----------------------------------------------------------------*/
11079 /* genGenPointerGet - gget value from generic pointer space        */
11080 /*-----------------------------------------------------------------*/
11081 static void genGenPointerGet (operand *left,
11082                               operand *result, iCode *ic)
11083 {
11084   int size, offset, lit;
11085   sym_link *letype = getSpec(operandType(left));
11086
11087     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11088     pic16_aopOp(left,ic,FALSE);
11089     pic16_aopOp(result,ic,TRUE);
11090     size = AOP_SIZE(result);
11091
11092     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11093   
11094     /* if bit then unpack */
11095     if (IS_BITFIELD(letype)) {
11096       genUnpackBits(result,left,"BAD",GPOINTER);
11097       goto release;
11098     }
11099
11100     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11101
11102       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11103       // load FSR0 from immediate
11104       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11105
11106       werror(W_POSSBUG2, __FILE__, __LINE__);
11107
11108       offset = 0;
11109       while(size--) {
11110         if(size) {
11111           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11112         } else {
11113           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11114         }
11115         offset++;
11116       }
11117
11118       goto release;
11119
11120     } else { /* we need to get it byte by byte */
11121
11122       /* set up WREG:PRODL:FSR0L with address from left */
11123       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11124       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11125       pic16_mov2w(AOP(left), 2);
11126       pic16_callGenericPointerRW(0, size);
11127       
11128       assignResultValue(result, 1);
11129       
11130       goto release;
11131     }
11132
11133 release:
11134   pic16_freeAsmop(left,NULL,ic,TRUE);
11135   pic16_freeAsmop(result,NULL,ic,TRUE);
11136 }
11137
11138 /*-----------------------------------------------------------------*/
11139 /* genConstPointerGet - get value from const generic pointer space */
11140 /*-----------------------------------------------------------------*/
11141 static void genConstPointerGet (operand *left,
11142                                 operand *result, iCode *ic)
11143 {
11144   //sym_link *retype = getSpec(operandType(result));
11145   // symbol *albl = newiTempLabel(NULL);        // patch 15
11146   // symbol *blbl = newiTempLabel(NULL);        //
11147   // PIC_OPCODE poc;                            // patch 15
11148   int size;
11149   int offset = 0;
11150
11151   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11152   pic16_aopOp(left,ic,FALSE);
11153   pic16_aopOp(result,ic,TRUE);
11154   size = AOP_SIZE(result);
11155
11156   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11157
11158   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11159
11160   // set up table pointer
11161   if( (AOP_TYPE(left) == AOP_PCODE) 
11162       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11163           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11164     {
11165       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11166       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11167       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11168       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11169       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11170       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11171   } else {
11172     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11173     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11174     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11175   }
11176
11177   while(size--) {
11178     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11179     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11180     offset++;
11181   }
11182     
11183   pic16_freeAsmop(left,NULL,ic,TRUE);
11184   pic16_freeAsmop(result,NULL,ic,TRUE);
11185 }
11186
11187
11188 /*-----------------------------------------------------------------*/
11189 /* genPointerGet - generate code for pointer get                   */
11190 /*-----------------------------------------------------------------*/
11191 static void genPointerGet (iCode *ic)
11192 {
11193   operand *left, *result ;
11194   sym_link *type, *etype;
11195   int p_type;
11196
11197     FENTRY;
11198     
11199     left = IC_LEFT(ic);
11200     result = IC_RESULT(ic) ;
11201
11202     /* depending on the type of pointer we need to
11203     move it to the correct pointer register */
11204     type = operandType(left);
11205     etype = getSpec(type);
11206
11207 #if 0
11208     if (IS_PTR_CONST(type))
11209 #else
11210     if (IS_CODEPTR(type))
11211 #endif
11212       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11213
11214     /* if left is of type of pointer then it is simple */
11215     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11216       p_type = DCL_TYPE(type);
11217     else {
11218       /* we have to go by the storage class */
11219       p_type = PTR_TYPE(SPEC_OCLS(etype));
11220
11221       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11222
11223       if (SPEC_OCLS(etype)->codesp ) {
11224         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11225         //p_type = CPOINTER ;   
11226       } else
11227       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11228         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11229         /*p_type = FPOINTER ;*/ 
11230       } else
11231       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11232         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11233         /* p_type = PPOINTER; */
11234       } else
11235       if (SPEC_OCLS(etype) == idata ) {
11236         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11237         /* p_type = IPOINTER; */
11238       } else {
11239         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11240         /* p_type = POINTER ; */
11241       }
11242     }
11243
11244     /* now that we have the pointer type we assign
11245     the pointer values */
11246     switch (p_type) {
11247       case POINTER:     
11248       case FPOINTER:
11249       case IPOINTER:
11250         genNearPointerGet (left,result,ic);
11251         break;
11252
11253       case PPOINTER:
11254         genPagedPointerGet(left,result,ic);
11255         break;
11256
11257 #if 0
11258       /* PICs do not support FAR pointers... */
11259       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11260       case FPOINTER:
11261         genFarPointerGet (left,result,ic);
11262         break;
11263 #endif
11264
11265       case CPOINTER:
11266         genConstPointerGet (left,result,ic);
11267         //pic16_emitcodePointerGet (left,result,ic);
11268         break;
11269
11270       case GPOINTER:
11271 #if 0
11272       if (IS_PTR_CONST(type))
11273         genConstPointerGet (left,result,ic);
11274       else
11275 #endif
11276         genGenPointerGet (left,result,ic);
11277       break;
11278
11279     default:
11280       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11281               "genPointerGet: illegal pointer type");
11282     
11283     }
11284 }
11285
11286 /*-----------------------------------------------------------------*/
11287 /* genPackBits - generates code for packed bit storage             */
11288 /*-----------------------------------------------------------------*/
11289 static void genPackBits (sym_link    *etype , operand *result,
11290                          operand *right ,
11291                          char *rname, int p_type)
11292 {
11293   int shCnt = 0 ;
11294   int offset = 0  ;
11295   int rLen = 0 ;
11296   int blen, bstr ;   
11297   int shifted_and_masked = 0;
11298   unsigned long lit = (unsigned long)-1;
11299   sym_link *retype;
11300
11301   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11302   blen = SPEC_BLEN(etype);
11303   bstr = SPEC_BSTR(etype);
11304
11305   retype = getSpec(operandType(right));
11306
11307   if(AOP_TYPE(right) == AOP_LIT) {
11308     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11309     
11310     if((blen == 1) && (bstr < 8)) {
11311       /* it is a single bit, so use the appropriate bit instructions */
11312
11313       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11314
11315       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11316         /* workaround to reduce the extra lfsr instruction */
11317         if(lit) {
11318           pic16_emitpcode(POC_BSF,
11319               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11320         } else {
11321           pic16_emitpcode(POC_BCF,
11322               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11323         }
11324       } else {
11325         if (PIC_IS_DATA_PTR(operandType(result))) {
11326           pic16_loadFSR0(result, 0);
11327           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11328               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11329         } else {
11330           /* get old value */
11331           pic16_derefPtr (result, p_type, 0, NULL);
11332           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11333               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11334           /* write back new value */
11335           pic16_derefPtr (result, p_type, 1, NULL);
11336         }
11337       }
11338
11339       return;
11340     }
11341     /* IORLW below is more efficient */
11342     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11343     lit = (lit & ((1UL << blen) - 1)) << bstr;
11344     shifted_and_masked = 1;
11345     offset++;
11346   } else
11347     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11348         && IS_BITFIELD(retype) 
11349         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11350         && (blen == 1)) {
11351       int rblen, rbstr;
11352
11353       rblen = SPEC_BLEN( retype );
11354       rbstr = SPEC_BSTR( retype );
11355
11356       if(IS_BITFIELD(etype)) {
11357         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11358         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11359       } else {
11360         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11361       }
11362
11363       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11364
11365       if(IS_BITFIELD(etype)) {
11366         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11367       } else {
11368         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11369       }
11370
11371       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11372
11373       return;
11374     } else {
11375       /* move right to W */
11376       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11377     }
11378
11379   /* if the bit length is less than or   */
11380   /* it exactly fits a byte then         */
11381   if((shCnt=SPEC_BSTR(etype))
11382       || SPEC_BLEN(etype) <= 8 )  {
11383     int fsr0_setup = 0;
11384
11385     if (blen != 8 || bstr != 0) {
11386       // we need to combine the value with the old value
11387       if(!shifted_and_masked)
11388       {
11389         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11390
11391         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11392             SPEC_BSTR(etype), SPEC_BLEN(etype));
11393
11394         /* shift left acc, do NOT mask the result again */
11395         AccLsh(shCnt, 0);
11396
11397         /* using PRODH as a temporary register here */
11398         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11399       }
11400
11401       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11402         || IS_DIRECT(result)) {
11403         /* access symbol directly */
11404         pic16_mov2w (AOP(result), 0);
11405       } else {
11406         /* get old value */
11407         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11408       }
11409 #if 1
11410       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11411             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11412                             (unsigned char)(0xff >> (8-bstr))) ));
11413       if (!shifted_and_masked) {
11414         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11415       } else {
11416         /* We have the shifted and masked (literal) right value in `lit' */
11417         if (lit != 0)
11418           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11419       }
11420     } // if (blen != 8 || bstr != 0)
11421
11422     /* write new value back */
11423     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11424         || IS_DIRECT(result)) {
11425       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11426     } else {
11427       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11428     }
11429 #endif
11430
11431     return;
11432   }
11433
11434
11435 #if 0
11436   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11437   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11438   exit(-1);
11439 #endif
11440
11441
11442   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11443   rLen = SPEC_BLEN(etype)-8;
11444
11445   /* now generate for lengths greater than one byte */
11446   while (1) {
11447     rLen -= 8 ;
11448     if (rLen <= 0 ) {
11449       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11450       break ;
11451     }
11452
11453     switch (p_type) {
11454       case POINTER:
11455         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11456         break;
11457
11458         /*
11459            case FPOINTER:
11460            MOVA(l);
11461            pic16_emitcode("movx","@dptr,a");
11462            break;
11463
11464            case GPOINTER:
11465            MOVA(l);
11466            DEBUGpic16_emitcode(";lcall","__gptrput");
11467            break;  
11468          */
11469       default:
11470         assert(0);
11471     }   
11472
11473
11474     pic16_mov2w(AOP(right), offset++);
11475   }
11476
11477   /* last last was not complete */
11478   if (rLen)   {
11479     /* save the byte & read byte */
11480     switch (p_type) {
11481       case POINTER:
11482         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11483         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11484         break;
11485
11486         /*
11487            case FPOINTER:
11488            pic16_emitcode ("mov","b,a");
11489            pic16_emitcode("movx","a,@dptr");
11490            break;
11491
11492            case GPOINTER:
11493            pic16_emitcode ("push","b");
11494            pic16_emitcode ("push","acc");
11495            pic16_emitcode ("lcall","__gptrget");
11496            pic16_emitcode ("pop","b");
11497            break;
11498          */
11499       default:
11500         assert(0);
11501     }
11502     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11503     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11504     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11505     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11506     //        pic16_emitcode ("orl","a,b");
11507   }
11508
11509   //    if (p_type == GPOINTER)
11510   //        pic16_emitcode("pop","b");
11511
11512   switch (p_type) {
11513
11514     case POINTER:
11515       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11516       //        pic16_emitcode("mov","@%s,a",rname);
11517       break;
11518       /*
11519          case FPOINTER:
11520          pic16_emitcode("movx","@dptr,a");
11521          break;
11522
11523          case GPOINTER:
11524          DEBUGpic16_emitcode(";lcall","__gptrput");
11525          break;                 
11526        */
11527     default:
11528       assert(0);
11529   }
11530
11531   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11532 }
11533
11534 /*-----------------------------------------------------------------*/
11535 /* genDataPointerSet - remat pointer to data space                 */
11536 /*-----------------------------------------------------------------*/
11537 static void genDataPointerSet(operand *right,
11538                               operand *result,
11539                               iCode *ic)
11540 {
11541   int size, offset = 0, resoffset=0 ;
11542
11543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11544     pic16_aopOp(right,ic,FALSE);
11545
11546     size = AOP_SIZE(right);
11547
11548 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11549
11550 #if 0
11551     if ( AOP_TYPE(result) == AOP_PCODE) {
11552       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11553               AOP(result)->aopu.pcop->name,
11554                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11555               PCOR(AOP(result)->aopu.pcop)->instance:
11556               PCOI(AOP(result)->aopu.pcop)->offset);
11557     }
11558 #endif
11559
11560     if(AOP(result)->aopu.pcop->type == PO_DIR)
11561       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11562
11563     while (size--) {
11564       if (AOP_TYPE(right) == AOP_LIT) {
11565         unsigned int lit;
11566
11567           if(!IS_FLOAT(operandType( right )))
11568             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11569           else {
11570             union {
11571               unsigned long lit_int;
11572               float lit_float;
11573             } info;
11574         
11575               /* take care if literal is a float */
11576               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11577               lit = info.lit_int;
11578           }
11579                     lit = lit >> (8*offset);
11580                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11581                 } else {
11582                   pic16_mov2w(AOP(right), offset);
11583                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11584                 }
11585                 offset++;
11586                 resoffset++;
11587         }
11588
11589     pic16_freeAsmop(right,NULL,ic,TRUE);
11590 }
11591
11592
11593
11594 /*-----------------------------------------------------------------*/
11595 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11596 /*-----------------------------------------------------------------*/
11597 static void genNearPointerSet (operand *right,
11598                                operand *result, 
11599                                iCode *ic)
11600 {
11601   asmop *aop = NULL;
11602   sym_link *retype;
11603   sym_link *ptype = operandType(result);
11604   sym_link *resetype;
11605     
11606     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11607     retype= getSpec(operandType(right));
11608     resetype = getSpec(operandType(result));
11609   
11610     pic16_aopOp(result,ic,FALSE);
11611     
11612     /* if the result is rematerializable &
11613      * in data space & not a bit variable */
11614         
11615     /* and result is not a bit variable */
11616     if (AOP_TYPE(result) == AOP_PCODE
11617 //      && AOP_TYPE(result) == AOP_IMMD
11618       && DCL_TYPE(ptype) == POINTER
11619       && !IS_BITFIELD(retype)
11620       && !IS_BITFIELD(resetype)) {
11621
11622         genDataPointerSet (right,result,ic);
11623         pic16_freeAsmop(result,NULL,ic,TRUE);
11624       return;
11625     }
11626
11627     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11628     pic16_aopOp(right,ic,FALSE);
11629     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11630
11631     /* if bitfield then unpack the bits */
11632     if (IS_BITFIELD(resetype)) {
11633       genPackBits (resetype, result, right, NULL, POINTER);
11634     } else {
11635       /* we have can just get the values */
11636       int size = AOP_SIZE(right);
11637       int offset = 0 ;    
11638
11639         pic16_loadFSR0(result, 0);
11640             
11641         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11642         while (size--) {
11643           if (AOP_TYPE(right) == AOP_LIT) {
11644             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11645             if (size) {
11646               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11647             } else {
11648               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11649             }
11650           } else { // no literal
11651             if(size) {
11652               pic16_emitpcode(POC_MOVFF,
11653                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11654                   pic16_popCopyReg(&pic16_pc_postinc0)));
11655             } else {
11656               pic16_emitpcode(POC_MOVFF,
11657                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11658                   pic16_popCopyReg(&pic16_pc_indf0)));
11659             }
11660           }
11661           
11662           offset++;
11663         }
11664     }
11665
11666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11667     /* now some housekeeping stuff */
11668     if (aop) {
11669       /* we had to allocate for this iCode */
11670       pic16_freeAsmop(NULL,aop,ic,TRUE);
11671     } else { 
11672       /* we did not allocate which means left
11673        * already in a pointer register, then
11674        * if size > 0 && this could be used again
11675        * we have to point it back to where it 
11676        * belongs */
11677       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11678       if (AOP_SIZE(right) > 1
11679         && !OP_SYMBOL(result)->remat
11680         && ( OP_SYMBOL(result)->liveTo > ic->seq
11681         || ic->depth )) {
11682
11683           int size = AOP_SIZE(right) - 1;
11684
11685             while (size--)
11686               pic16_emitcode("decf","fsr0,f");
11687               //pic16_emitcode("dec","%s",rname);
11688       }
11689     }
11690
11691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11692     /* done */
11693 //release:
11694     pic16_freeAsmop(right,NULL,ic,TRUE);
11695     pic16_freeAsmop(result,NULL,ic,TRUE);
11696 }
11697
11698 /*-----------------------------------------------------------------*/
11699 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11700 /*-----------------------------------------------------------------*/
11701 static void genPagedPointerSet (operand *right,
11702                                operand *result, 
11703                                iCode *ic)
11704 {
11705     asmop *aop = NULL;
11706     regs *preg = NULL ;
11707     char *rname , *l;
11708     sym_link *retype;
11709        
11710     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11711
11712     retype= getSpec(operandType(right));
11713     
11714     pic16_aopOp(result,ic,FALSE);
11715     
11716     /* if the value is already in a pointer register
11717        then don't need anything more */
11718     if (!AOP_INPREG(AOP(result))) {
11719         /* otherwise get a free pointer register */
11720         aop = newAsmop(0);
11721         preg = getFreePtr(ic,&aop,FALSE);
11722         pic16_emitcode("mov","%s,%s",
11723                 preg->name,
11724                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11725         rname = preg->name ;
11726     } else
11727         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11728     
11729     pic16_freeAsmop(result,NULL,ic,TRUE);
11730     pic16_aopOp (right,ic,FALSE);
11731
11732     /* if bitfield then unpack the bits */
11733     if (IS_BITFIELD(retype)) 
11734         genPackBits (retype,result,right,rname,PPOINTER);
11735     else {
11736         /* we have can just get the values */
11737         int size = AOP_SIZE(right);
11738         int offset = 0 ;        
11739         
11740         while (size--) {
11741             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11742             
11743             MOVA(l);
11744             pic16_emitcode("movx","@%s,a",rname);
11745
11746             if (size)
11747                 pic16_emitcode("inc","%s",rname);
11748
11749             offset++;
11750         }
11751     }
11752     
11753     /* now some housekeeping stuff */
11754     if (aop) {
11755         /* we had to allocate for this iCode */
11756         pic16_freeAsmop(NULL,aop,ic,TRUE);
11757     } else { 
11758         /* we did not allocate which means left
11759            already in a pointer register, then
11760            if size > 0 && this could be used again
11761            we have to point it back to where it 
11762            belongs */
11763         if (AOP_SIZE(right) > 1 &&
11764             !OP_SYMBOL(result)->remat &&
11765             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11766               ic->depth )) {
11767             int size = AOP_SIZE(right) - 1;
11768             while (size--)
11769                 pic16_emitcode("dec","%s",rname);
11770         }
11771     }
11772
11773     /* done */
11774     pic16_freeAsmop(right,NULL,ic,TRUE);
11775     
11776         
11777 }
11778
11779 #if 0
11780 /* This code is not adjusted to PIC16 and fails utterly...
11781  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11782
11783 /*-----------------------------------------------------------------*/
11784 /* genFarPointerSet - set value from far space                     */
11785 /*-----------------------------------------------------------------*/
11786 static void genFarPointerSet (operand *right,
11787                               operand *result, iCode *ic)
11788 {
11789     int size, offset ;
11790     sym_link *retype = getSpec(operandType(right));
11791
11792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11793     pic16_aopOp(result,ic,FALSE);
11794
11795     /* if the operand is already in dptr 
11796     then we do nothing else we move the value to dptr */
11797     if (AOP_TYPE(result) != AOP_STR) {
11798         /* if this is remateriazable */
11799         if (AOP_TYPE(result) == AOP_IMMD)
11800             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11801         else { /* we need to get it byte by byte */
11802             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11803             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11804             if (options.model == MODEL_FLAT24)
11805             {
11806                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11807             }
11808         }
11809     }
11810     /* so dptr know contains the address */
11811     pic16_freeAsmop(result,NULL,ic,TRUE);
11812     pic16_aopOp(right,ic,FALSE);
11813
11814     /* if bit then unpack */
11815     if (IS_BITFIELD(retype)) 
11816         genPackBits(retype,result,right,"dptr",FPOINTER);
11817     else {
11818         size = AOP_SIZE(right);
11819         offset = 0 ;
11820
11821         while (size--) {
11822             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11823             MOVA(l);
11824             pic16_emitcode("movx","@dptr,a");
11825             if (size)
11826                 pic16_emitcode("inc","dptr");
11827         }
11828     }
11829
11830     pic16_freeAsmop(right,NULL,ic,TRUE);
11831 }
11832 #endif
11833
11834 /*-----------------------------------------------------------------*/
11835 /* genGenPointerSet - set value from generic pointer space         */
11836 /*-----------------------------------------------------------------*/
11837 #if 0
11838 static void genGenPointerSet (operand *right,
11839                               operand *result, iCode *ic)
11840 {
11841         int i, size, offset, lit;
11842         sym_link *retype = getSpec(operandType(right));
11843
11844         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11845
11846         pic16_aopOp(result,ic,FALSE);
11847         pic16_aopOp(right,ic,FALSE);
11848         size = AOP_SIZE(right);
11849         offset = 0;
11850
11851         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11852
11853         /* if the operand is already in dptr 
11854                 then we do nothing else we move the value to dptr */
11855         if (AOP_TYPE(result) != AOP_STR) {
11856                 /* if this is remateriazable */
11857                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11858                 // WARNING: anythig until "else" is untested!
11859                 if (AOP_TYPE(result) == AOP_IMMD) {
11860                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11861                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11862                         // load FSR0 from immediate
11863                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11864                         offset = 0;
11865                         while(size--) {
11866                                 if(size) {
11867                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11868                                 } else {
11869                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11870                                 }
11871                                 offset++;
11872                         }
11873                         goto release;
11874                 }
11875                 else { /* we need to get it byte by byte */
11876                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11877                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11878
11879                         // set up FSR0 with address of result
11880                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11881                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11882
11883                         /* hack hack! see if this the FSR. If so don't load W */
11884                         if(AOP_TYPE(right) != AOP_ACC) {
11885
11886                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11887
11888                                 if(AOP_TYPE(right) == AOP_LIT)
11889                                 {
11890                                         // copy literal
11891                                         // note: pic16_popGet handles sign extension
11892                                         for(i=0;i<size;i++) {
11893                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11894                                                 if(i < size-1)
11895                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11896                                                 else
11897                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11898                                         }
11899                                 } else {
11900                                         // copy regs
11901
11902                                         for(i=0;i<size;i++) {
11903                                                 if(i < size-1)
11904                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11905                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11906                                                 else
11907                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11908                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11909                                         }
11910                                 }
11911                                 goto release;
11912                         } 
11913                         // right = ACC
11914                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11915                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11916                         goto release;
11917         } // if (AOP_TYPE(result) != AOP_IMMD)
11918
11919         } // if (AOP_TYPE(result) != AOP_STR)
11920         /* so dptr know contains the address */
11921
11922
11923         /* if bit then unpack */
11924         if (IS_BITFIELD(retype)) 
11925                 genPackBits(retype,result,right,"dptr",GPOINTER);
11926         else {
11927                 size = AOP_SIZE(right);
11928                 offset = 0 ;
11929
11930                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11931
11932                 // set up FSR0 with address of result
11933                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11934                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11935         
11936                 while (size--) {
11937                         if (AOP_TYPE(right) == AOP_LIT) {
11938                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11939                                 if (size) {
11940                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11941                                 } else {
11942                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11943                                 }
11944                         } else { // no literal
11945                                 if(size) {
11946                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11947                                 } else {
11948                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11949                                 }
11950                         }
11951                         offset++;
11952                 }
11953         }
11954
11955         release:
11956         pic16_freeAsmop(right,NULL,ic,TRUE);
11957         pic16_freeAsmop(result,NULL,ic,TRUE);
11958 }
11959 #endif
11960
11961 static void genGenPointerSet (operand *right,
11962                               operand *result, iCode *ic)
11963 {
11964   int size;
11965   sym_link *retype = getSpec(operandType(result));
11966
11967     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11968
11969     pic16_aopOp(result,ic,FALSE);
11970     pic16_aopOp(right,ic,FALSE);
11971     size = AOP_SIZE(right);
11972
11973     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11974
11975
11976     /* if bit then unpack */
11977     if (IS_BITFIELD(retype)) {
11978 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11979       genPackBits(retype,result,right,"dptr",GPOINTER);
11980       goto release;
11981     }
11982
11983     size = AOP_SIZE(right);
11984
11985     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11986
11987
11988     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11989
11990     /* value of right+0 is placed on stack, which will be retrieved
11991      * by the support function thus restoring the stack. The important
11992      * thing is that there is no need to manually restore stack pointer
11993      * here */
11994     pushaop(AOP(right), 0);
11995 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11996     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11997     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11998     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11999     
12000     /* load address to write to in WREG:FSR0H:FSR0L */
12001     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12002                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12003     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12004                                 pic16_popCopyReg(&pic16_pc_prodl)));
12005     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12006     
12007     pic16_callGenericPointerRW(1, size);
12008
12009 release:
12010     pic16_freeAsmop(right,NULL,ic,TRUE);
12011     pic16_freeAsmop(result,NULL,ic,TRUE);
12012 }
12013
12014 /*-----------------------------------------------------------------*/
12015 /* genPointerSet - stores the value into a pointer location        */
12016 /*-----------------------------------------------------------------*/
12017 static void genPointerSet (iCode *ic)
12018 {    
12019   operand *right, *result ;
12020   sym_link *type, *etype;
12021   int p_type;
12022
12023     FENTRY;
12024
12025     right = IC_RIGHT(ic);
12026     result = IC_RESULT(ic) ;
12027
12028     /* depending on the type of pointer we need to
12029     move it to the correct pointer register */
12030     type = operandType(result);
12031     etype = getSpec(type);
12032     
12033     /* if left is of type of pointer then it is simple */
12034     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12035         p_type = DCL_TYPE(type);
12036     }
12037     else {
12038         /* we have to go by the storage class */
12039         p_type = PTR_TYPE(SPEC_OCLS(etype));
12040
12041 /*      if (SPEC_OCLS(etype)->codesp ) { */
12042 /*          p_type = CPOINTER ;  */
12043 /*      } */
12044 /*      else */
12045 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12046 /*              p_type = FPOINTER ; */
12047 /*          else */
12048 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12049 /*                  p_type = PPOINTER ; */
12050 /*              else */
12051 /*                  if (SPEC_OCLS(etype) == idata ) */
12052 /*                      p_type = IPOINTER ; */
12053 /*                  else */
12054 /*                      p_type = POINTER ; */
12055     }
12056
12057     /* now that we have the pointer type we assign
12058     the pointer values */
12059     switch (p_type) {
12060       case POINTER:
12061       case FPOINTER:
12062       case IPOINTER:
12063         genNearPointerSet (right,result,ic);
12064         break;
12065
12066       case PPOINTER:
12067         genPagedPointerSet (right,result,ic);
12068         break;
12069
12070 #if 0
12071       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12072       case FPOINTER:
12073         genFarPointerSet (right,result,ic);
12074         break;
12075 #endif
12076         
12077       case GPOINTER:
12078         genGenPointerSet (right,result,ic);
12079         break;
12080
12081       default:
12082         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12083           "genPointerSet: illegal pointer type");
12084     }
12085 }
12086
12087 /*-----------------------------------------------------------------*/
12088 /* genIfx - generate code for Ifx statement                        */
12089 /*-----------------------------------------------------------------*/
12090 static void genIfx (iCode *ic, iCode *popIc)
12091 {
12092   operand *cond = IC_COND(ic);
12093   int isbit =0;
12094
12095     FENTRY;
12096
12097     pic16_aopOp(cond,ic,FALSE);
12098
12099     /* get the value into acc */
12100     if (AOP_TYPE(cond) != AOP_CRY)
12101       pic16_toBoolean(cond);
12102     else
12103       isbit = 1;
12104     /* the result is now in the accumulator */
12105     pic16_freeAsmop(cond,NULL,ic,TRUE);
12106
12107     /* if there was something to be popped then do it */
12108     if (popIc)
12109       genIpop(popIc);
12110
12111     /* if the condition is  a bit variable */
12112     if (isbit && IS_ITEMP(cond) && 
12113         SPIL_LOC(cond)) {
12114       genIfxJump(ic,"c");
12115       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12116     } else {
12117       if (isbit && !IS_ITEMP(cond))
12118         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12119         else
12120         genIfxJump(ic,"a");
12121     }
12122     ic->generated = 1;
12123 }
12124
12125 /*-----------------------------------------------------------------*/
12126 /* genAddrOf - generates code for address of                       */
12127 /*-----------------------------------------------------------------*/
12128 static void genAddrOf (iCode *ic)
12129 {
12130   operand *result, *left;
12131   int size;
12132   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12133   pCodeOp *pcop0, *pcop1, *pcop2;
12134
12135     FENTRY;
12136
12137     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12138
12139     sym = OP_SYMBOL( IC_LEFT(ic) );
12140     
12141     if(sym->onStack) {
12142       /* get address of symbol on stack */
12143       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12144 #if 0
12145       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12146                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12147 #endif
12148
12149       // operands on stack are accessible via "FSR2 + index" with index
12150       // starting at 2 for arguments and growing from 0 downwards for
12151       // local variables (index == 0 is not assigned so we add one here)
12152       {
12153         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12154
12155           if (soffs <= 0) {
12156             assert (soffs < 0);
12157             soffs++;
12158           } // if
12159
12160           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12161           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12162           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12163           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12164           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12165           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12166           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12167       }
12168
12169       goto release;
12170     }
12171         
12172 //      if(pic16_debug_verbose) {
12173 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12174 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12175 //      }
12176         
12177     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12178     size = AOP_SIZE(IC_RESULT(ic));
12179
12180     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12181     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12182     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12183         
12184     if (size == 3) {
12185       pic16_emitpcode(POC_MOVLW, pcop0);
12186       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12187       pic16_emitpcode(POC_MOVLW, pcop1);
12188       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12189       pic16_emitpcode(POC_MOVLW, pcop2);
12190       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12191     } else
12192     if (size == 2) {
12193       pic16_emitpcode(POC_MOVLW, pcop0);
12194       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12195       pic16_emitpcode(POC_MOVLW, pcop1);
12196     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12197     } else {
12198       pic16_emitpcode(POC_MOVLW, pcop0);
12199       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12200     }
12201
12202     pic16_freeAsmop(left, NULL, ic, FALSE);
12203 release:
12204     pic16_freeAsmop(result,NULL,ic,TRUE);
12205 }
12206
12207
12208 #if 0
12209 /*-----------------------------------------------------------------*/
12210 /* genFarFarAssign - assignment when both are in far space         */
12211 /*-----------------------------------------------------------------*/
12212 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12213 {
12214     int size = AOP_SIZE(right);
12215     int offset = 0;
12216     char *l ;
12217     /* first push the right side on to the stack */
12218     while (size--) {
12219         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12220         MOVA(l);
12221         pic16_emitcode ("push","acc");
12222     }
12223     
12224     pic16_freeAsmop(right,NULL,ic,FALSE);
12225     /* now assign DPTR to result */
12226     pic16_aopOp(result,ic,FALSE);
12227     size = AOP_SIZE(result);
12228     while (size--) {
12229         pic16_emitcode ("pop","acc");
12230         pic16_aopPut(AOP(result),"a",--offset);
12231     }
12232     pic16_freeAsmop(result,NULL,ic,FALSE);
12233         
12234 }
12235 #endif
12236
12237 /*-----------------------------------------------------------------*/
12238 /* genAssign - generate code for assignment                        */
12239 /*-----------------------------------------------------------------*/
12240 static void genAssign (iCode *ic)
12241 {
12242   operand *result, *right;
12243   sym_link *restype, *rtype;
12244   int size, offset,know_W;
12245   unsigned long lit = 0L;
12246
12247     result = IC_RESULT(ic);
12248     right  = IC_RIGHT(ic) ;
12249
12250     FENTRY;
12251   
12252     /* if they are the same */
12253     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12254       return ;
12255
12256     /* reversed order operands are aopOp'ed so that result operand
12257      * is effective in case right is a stack symbol. This maneauver
12258      * allows to use the _G.resDirect flag later */
12259      pic16_aopOp(result,ic,TRUE);
12260     pic16_aopOp(right,ic,FALSE);
12261
12262     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12263
12264     /* if they are the same registers */
12265     if (pic16_sameRegs(AOP(right),AOP(result)))
12266       goto release;
12267
12268     /* if the result is a bit */
12269     if (AOP_TYPE(result) == AOP_CRY) {
12270       /* if the right size is a literal then
12271          we know what the value is */
12272       if (AOP_TYPE(right) == AOP_LIT) {
12273           
12274         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12275             pic16_popGet(AOP(result),0));
12276
12277         if (((int) operandLitValue(right))) 
12278           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12279               AOP(result)->aopu.aop_dir,
12280               AOP(result)->aopu.aop_dir);
12281         else
12282           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12283               AOP(result)->aopu.aop_dir,
12284               AOP(result)->aopu.aop_dir);
12285         
12286         goto release;
12287       }
12288
12289       /* the right is also a bit variable */
12290       if (AOP_TYPE(right) == AOP_CRY) {
12291         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12292         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12293         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12294
12295         goto release ;
12296       }
12297
12298       /* we need to or */
12299       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12300       pic16_toBoolean(right);
12301       emitSKPZ;
12302       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12303       //pic16_aopPut(AOP(result),"a",0);
12304       goto release ;
12305     }
12306
12307     /* bit variables done */
12308     /* general case */
12309     size = AOP_SIZE(result);
12310     offset = 0 ;
12311
12312   /* bit variables done */
12313   /* general case */
12314   size = AOP_SIZE(result);
12315   restype = operandType(result);
12316   rtype = operandType(right);
12317   offset = 0 ;
12318
12319   if(AOP_TYPE(right) == AOP_LIT) {
12320     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12321     {
12322       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12323
12324       /* patch tag for literals that are cast to pointers */
12325       if (IS_CODEPTR(restype)) {
12326         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12327         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12328       } else {
12329         if (IS_GENPTR(restype))
12330         {
12331           if (IS_CODEPTR(rtype)) {
12332             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12333             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12334           } else if (PIC_IS_DATA_PTR(rtype)) {
12335             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12336             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12337           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12338             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12339           } else if (IS_PTR(rtype)) {
12340             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12341             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12342           }
12343         }
12344       }
12345     } else {
12346       union {
12347         unsigned long lit_int;
12348         float lit_float;
12349       } info;
12350
12351
12352       if(IS_FIXED16X16(operandType(right))) {
12353         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12354       } else {
12355         /* take care if literal is a float */
12356         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12357         lit = info.lit_int;
12358       }
12359     }
12360   }
12361
12362 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12363 //                      sizeof(unsigned long int), sizeof(float));
12364
12365
12366     if (AOP_TYPE(right) == AOP_REG) {
12367       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12368       while (size--) {
12369         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12370       } // while
12371       goto release;
12372     }
12373
12374     /* when do we have to read the program memory?
12375      * - if right itself is a symbol in code space
12376      *   (we don't care what it points to if it's a pointer)
12377      * - AND right is not a function (we would want its address)
12378      */
12379     if(AOP_TYPE(right) != AOP_LIT
12380       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12381       && !IS_FUNC(OP_SYM_TYPE(right))
12382       && !IS_ITEMP(right)) {
12383
12384       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12385       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12386       
12387       // set up table pointer
12388       if(is_LitOp(right)) {
12389 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12390         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12391         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12392         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12393         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12394         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12395         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12396       } else {
12397 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12398         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12399             pic16_popCopyReg(&pic16_pc_tblptrl)));
12400         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12401             pic16_popCopyReg(&pic16_pc_tblptrh)));
12402         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12403             pic16_popCopyReg(&pic16_pc_tblptru)));
12404       }
12405
12406       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12407       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12408       while(size--) {
12409         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12410         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12411             pic16_popGet(AOP(result),offset)));
12412         offset++;
12413       }
12414
12415       /* FIXME: for pointers we need to extend differently (according
12416        * to pointer type DATA/CODE/EEPROM/... :*/
12417       size = getSize(OP_SYM_TYPE(right));
12418       if(AOP_SIZE(result) > size) {
12419         size = AOP_SIZE(result) - size;
12420         while(size--) {
12421           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12422           offset++;
12423         }
12424       }
12425       goto release;
12426     }
12427
12428 #if 0
12429     /* VR - What is this?! */
12430     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12431       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12432       
12433       if(aopIdx(AOP(result),0) == 4) {
12434         /* this is a workaround to save value of right into wreg too,
12435          * value of wreg is going to be used later */
12436         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12437         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12438         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12439         goto release;
12440       } else
12441 //      assert(0);
12442       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12443     }
12444 #endif
12445
12446   know_W=-1;
12447   while (size--) {
12448     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12449     if(AOP_TYPE(right) == AOP_LIT) {
12450       if(lit&0xff) {
12451         if(know_W != (lit&0xff))
12452           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12453         know_W = lit&0xff;
12454         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12455       } else
12456         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12457
12458       lit >>= 8;
12459
12460     } else if (AOP_TYPE(right) == AOP_CRY) {
12461       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12462       if(offset == 0) {
12463         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12464         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12465         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12466       }
12467     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12468         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12469         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12470     } else {
12471       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12472
12473       if(!_G.resDirect)         /* use this aopForSym feature */
12474         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12475     }
12476       
12477       offset++;
12478     }
12479   
12480 release:
12481   pic16_freeAsmop (right,NULL,ic,FALSE);
12482   pic16_freeAsmop (result,NULL,ic,TRUE);
12483
12484
12485 /*-----------------------------------------------------------------*/
12486 /* genJumpTab - generates code for jump table                       */
12487 /*-----------------------------------------------------------------*/
12488 static void genJumpTab (iCode *ic)
12489 {
12490   symbol *jtab;
12491   char *l;
12492   pCodeOp *jt_offs;
12493   pCodeOp *jt_offs_hi;
12494   pCodeOp *jt_label;
12495
12496     FENTRY;
12497
12498     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12499     /* get the condition into accumulator */
12500     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12501     MOVA(l);
12502     /* multiply by three */
12503     pic16_emitcode("add","a,acc");
12504     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12505
12506     jtab = newiTempLabel(NULL);
12507     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12508     pic16_emitcode("jmp","@a+dptr");
12509     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12510
12511 #if 0
12512     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12513     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12514     emitSKPNC;
12515     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12516     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12517     pic16_emitpLabel(jtab->key);
12518
12519 #else
12520
12521     jt_offs = pic16_popGetTempReg(0);
12522     jt_offs_hi = pic16_popGetTempReg(1);
12523     jt_label = pic16_popGetLabel (jtab->key);
12524     //fprintf (stderr, "Creating jump table...\n");
12525
12526     // calculate offset into jump table (idx * sizeof (GOTO))
12527     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12528     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12529     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12530     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12531     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12532     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12533     pic16_emitpcode(POC_MOVWF , jt_offs);
12534
12535     // prepare PCLATx (set to first entry in jump table)
12536     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12537     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12538     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12539     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12540     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12541
12542     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12543     pic16_emitpcode(POC_ADDWF , jt_offs);
12544     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12545     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12546     emitSKPNC;
12547     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12548
12549     // release temporaries and prepare jump into table (new PCL --> WREG)
12550     pic16_emitpcode(POC_MOVFW , jt_offs);
12551     pic16_popReleaseTempReg (jt_offs_hi, 1);
12552     pic16_popReleaseTempReg (jt_offs, 0);
12553
12554     // jump into the table
12555     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12556
12557     pic16_emitpLabelFORCE(jtab->key);
12558 #endif
12559
12560     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12561 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12562
12563     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12564     /* now generate the jump labels */
12565     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12566          jtab = setNextItem(IC_JTLABELS(ic))) {
12567 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12568         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12569         
12570     }
12571     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12572
12573 }
12574
12575 /*-----------------------------------------------------------------*/
12576 /* genMixedOperation - gen code for operators between mixed types  */
12577 /*-----------------------------------------------------------------*/
12578 /*
12579   TSD - Written for the PIC port - but this unfortunately is buggy.
12580   This routine is good in that it is able to efficiently promote 
12581   types to different (larger) sizes. Unfortunately, the temporary
12582   variables that are optimized out by this routine are sometimes
12583   used in other places. So until I know how to really parse the 
12584   iCode tree, I'm going to not be using this routine :(.
12585 */
12586 static int genMixedOperation (iCode *ic)
12587 {
12588 #if 0
12589   operand *result = IC_RESULT(ic);
12590   sym_link *ctype = operandType(IC_LEFT(ic));
12591   operand *right = IC_RIGHT(ic);
12592   int ret = 0;
12593   int big,small;
12594   int offset;
12595
12596   iCode *nextic;
12597   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12598
12599   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12600
12601   nextic = ic->next;
12602   if(!nextic)
12603     return 0;
12604
12605   nextright = IC_RIGHT(nextic);
12606   nextleft  = IC_LEFT(nextic);
12607   nextresult = IC_RESULT(nextic);
12608
12609   pic16_aopOp(right,ic,FALSE);
12610   pic16_aopOp(result,ic,FALSE);
12611   pic16_aopOp(nextright,  nextic, FALSE);
12612   pic16_aopOp(nextleft,   nextic, FALSE);
12613   pic16_aopOp(nextresult, nextic, FALSE);
12614
12615   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12616
12617     operand *t = right;
12618     right = nextright;
12619     nextright = t; 
12620
12621     pic16_emitcode(";remove right +","");
12622
12623   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12624 /*
12625     operand *t = right;
12626     right = nextleft;
12627     nextleft = t; 
12628 */
12629     pic16_emitcode(";remove left +","");
12630   } else
12631     return 0;
12632
12633   big = AOP_SIZE(nextleft);
12634   small = AOP_SIZE(nextright);
12635
12636   switch(nextic->op) {
12637
12638   case '+':
12639     pic16_emitcode(";optimize a +","");
12640     /* if unsigned or not an integral type */
12641     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12642       pic16_emitcode(";add a bit to something","");
12643     } else {
12644
12645       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12646
12647       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12648         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12649         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12650       } else
12651         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12652
12653       offset = 0;
12654       while(--big) {
12655
12656         offset++;
12657
12658         if(--small) {
12659           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12660             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12661             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12662           }
12663
12664           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12665           emitSKPNC;
12666           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12667                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12668                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12669           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12670           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12671
12672         } else {
12673           pic16_emitcode("rlf","known_zero,w");
12674
12675           /*
12676             if right is signed
12677               btfsc  right,7
12678                addlw ff
12679           */
12680           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12681             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12682             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12683           } else {
12684             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12685           }
12686         }
12687       }
12688       ret = 1;
12689     }
12690   }
12691   ret = 1;
12692
12693 release:
12694   pic16_freeAsmop(right,NULL,ic,TRUE);
12695   pic16_freeAsmop(result,NULL,ic,TRUE);
12696   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12697   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12698   if(ret)
12699     nextic->generated = 1;
12700
12701   return ret;
12702 #else
12703   return 0;
12704 #endif
12705 }
12706 /*-----------------------------------------------------------------*/
12707 /* genCast - gen code for casting                                  */
12708 /*-----------------------------------------------------------------*/
12709 static void genCast (iCode *ic)
12710 {
12711   operand *result = IC_RESULT(ic);
12712   sym_link *ctype = operandType(IC_LEFT(ic));
12713   sym_link *rtype = operandType(IC_RIGHT(ic));
12714   sym_link *restype = operandType(IC_RESULT(ic));
12715   operand *right = IC_RIGHT(ic);
12716   int size, offset ;
12717
12718
12719     FENTRY;
12720
12721         /* if they are equivalent then do nothing */
12722 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12723 //              return ;
12724
12725         pic16_aopOp(result,ic,FALSE);
12726         pic16_aopOp(right,ic,FALSE) ;
12727
12728         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12729
12730
12731         /* if the result is a bit */
12732         if (AOP_TYPE(result) == AOP_CRY) {
12733         
12734                 /* if the right size is a literal then
12735                  * we know what the value is */
12736                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12737
12738                 if (AOP_TYPE(right) == AOP_LIT) {
12739                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12740                                 pic16_popGet(AOP(result),0));
12741
12742                         if (((int) operandLitValue(right))) 
12743                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12744                                         AOP(result)->aopu.aop_dir,
12745                                         AOP(result)->aopu.aop_dir);
12746                         else
12747                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12748                                         AOP(result)->aopu.aop_dir,
12749                                         AOP(result)->aopu.aop_dir);
12750                         goto release;
12751                 }
12752
12753                 /* the right is also a bit variable */
12754                 if (AOP_TYPE(right) == AOP_CRY) {
12755                         emitCLRC;
12756                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12757
12758                         pic16_emitcode("clrc","");
12759                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12760                                 AOP(right)->aopu.aop_dir,
12761                                 AOP(right)->aopu.aop_dir);
12762                         pic16_aopPut(AOP(result),"c",0);
12763                         goto release ;
12764                 }
12765
12766                 /* we need to or */
12767                 if (AOP_TYPE(right) == AOP_REG) {
12768                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12769                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12770                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12771                 }
12772                 pic16_toBoolean(right);
12773                 pic16_aopPut(AOP(result),"a",0);
12774                 goto release ;
12775         }
12776
12777         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12778           int offset = 1;
12779
12780                 size = AOP_SIZE(result);
12781
12782                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12783
12784                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12785                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12786                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12787
12788                 while (size--)
12789                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12790
12791                 goto release;
12792         }
12793
12794         if(IS_BITFIELD(getSpec(restype))
12795           && IS_BITFIELD(getSpec(rtype))) {
12796           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12797         }
12798         
12799         /* port from pic14 to cope with generic pointers */
12800         if (PIC_IS_TAGGED(restype))
12801         {
12802           operand *result = IC_RESULT(ic);
12803           //operand *left = IC_LEFT(ic);
12804           operand *right = IC_RIGHT(ic);
12805           int tag = 0xff;
12806
12807           /* copy common part */
12808           int max, size = AOP_SIZE(result);
12809           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12810           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12811
12812           max = size;
12813           while (size--)
12814           {
12815             pic16_mov2w (AOP(right), size);
12816             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12817           } // while
12818
12819           /* upcast into generic pointer type? */
12820           if (IS_GENPTR(restype)
12821               && !PIC_IS_TAGGED(rtype)
12822               && (AOP_SIZE(result) > max))
12823           {
12824             /* determine appropriate tag for right */
12825             if (PIC_IS_DATA_PTR(rtype))
12826               tag = GPTR_TAG_DATA;
12827             else if (IS_CODEPTR(rtype))
12828               tag = GPTR_TAG_CODE;
12829             else if (PIC_IS_DATA_PTR(ctype)) {
12830               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12831               tag = GPTR_TAG_DATA;
12832             } else if (IS_CODEPTR(ctype)) {
12833               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12834               tag = GPTR_TAG_CODE;
12835             } else if (IS_PTR(rtype)) {
12836               PERFORM_ONCE(weirdcast,
12837               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12838               );
12839               tag = GPTR_TAG_DATA;
12840             } else {
12841               PERFORM_ONCE(weirdcast,
12842               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12843               );
12844               tag = GPTR_TAG_DATA;
12845             }
12846
12847             assert (AOP_SIZE(result) == 3);
12848             /* zero-extend address... */
12849             for (size = max; size < AOP_SIZE(result)-1; size++)
12850               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12851             /* ...and add tag */
12852             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12853           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12854             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12855             for (size = max; size < AOP_SIZE(result)-1; size++)
12856               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12857             /* add __code tag */
12858             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12859           } else if (AOP_SIZE(result) > max) {
12860             /* extend non-pointers */
12861             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12862             pic16_addSign(result, max, 0);
12863           } // if
12864           goto release;
12865         }
12866
12867         /* if they are the same size : or less */
12868         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12869
12870                 /* if they are in the same place */
12871                 if (pic16_sameRegs(AOP(right),AOP(result)))
12872                         goto release;
12873
12874                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12875 #if 0
12876                 if (IS_PTR_CONST(rtype))
12877 #else
12878                 if (IS_CODEPTR(rtype))
12879 #endif
12880                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12881
12882 #if 0
12883                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12884 #else
12885                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12886 #endif
12887                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12888
12889 #if 0
12890                 if(AOP_TYPE(right) == AOP_IMMD) {
12891                   pCodeOp *pcop0, *pcop1, *pcop2;
12892                   symbol *sym = OP_SYMBOL( right );
12893
12894                         size = AOP_SIZE(result);
12895                         /* low */
12896                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12897                         /* high */
12898                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12899                         /* upper */
12900                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12901         
12902                         if (size == 3) {
12903                                 pic16_emitpcode(POC_MOVLW, pcop0);
12904                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12905                                 pic16_emitpcode(POC_MOVLW, pcop1);
12906                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12907                                 pic16_emitpcode(POC_MOVLW, pcop2);
12908                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12909                         } else
12910                         if (size == 2) {
12911                                 pic16_emitpcode(POC_MOVLW, pcop0);
12912                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12913                                 pic16_emitpcode(POC_MOVLW, pcop1);
12914                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12915                         } else {
12916                                 pic16_emitpcode(POC_MOVLW, pcop0);
12917                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12918                         }
12919                 } else
12920 #endif
12921                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12922                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12923                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12924                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12925                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12926                         if(AOP_SIZE(result) <2)
12927                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12928                 } else {
12929                         /* if they in different places then copy */
12930                         size = AOP_SIZE(result);
12931                         offset = 0 ;
12932                         while (size--) {
12933                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12934                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12935                                 offset++;
12936                         }
12937                 }
12938                 goto release;
12939         }
12940
12941         /* if the result is of type pointer */
12942         if (IS_PTR(ctype)) {
12943           int p_type;
12944           sym_link *type = operandType(right);
12945           sym_link *etype = getSpec(type);
12946
12947                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12948
12949                 /* pointer to generic pointer */
12950                 if (IS_GENPTR(ctype)) {
12951                   char *l = zero;
12952             
12953                         if (IS_PTR(type)) 
12954                                 p_type = DCL_TYPE(type);
12955                         else {
12956                 /* we have to go by the storage class */
12957                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12958
12959 /*              if (SPEC_OCLS(etype)->codesp )  */
12960 /*                  p_type = CPOINTER ;  */
12961 /*              else */
12962 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12963 /*                      p_type = FPOINTER ; */
12964 /*                  else */
12965 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12966 /*                          p_type = PPOINTER; */
12967 /*                      else */
12968 /*                          if (SPEC_OCLS(etype) == idata ) */
12969 /*                              p_type = IPOINTER ; */
12970 /*                          else */
12971 /*                              p_type = POINTER ; */
12972             }
12973                 
12974             /* the first two bytes are known */
12975       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12976             size = GPTRSIZE - 1; 
12977             offset = 0 ;
12978             while (size--) {
12979               if(offset < AOP_SIZE(right)) {
12980                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12981                 pic16_mov2f(AOP(result), AOP(right), offset);
12982 /*
12983                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12984                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12985                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12986                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12987                 } else { 
12988                   
12989                   pic16_aopPut(AOP(result),
12990                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12991                          offset);
12992                 }
12993 */
12994               } else 
12995                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12996               offset++;
12997             }
12998             /* the last byte depending on type */
12999             switch (p_type) {
13000             case IPOINTER:
13001             case POINTER:
13002             case FPOINTER:
13003                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13004                 break;
13005
13006             case CPOINTER:
13007                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13008                 break;
13009
13010             case PPOINTER:
13011               pic16_emitcode(";BUG!? ","%d",__LINE__);
13012                 l = "#0x03";
13013                 break;
13014
13015             case GPOINTER:
13016                 if (GPTRSIZE > AOP_SIZE(right)) {
13017                   // assume __data pointer... THIS MIGHT BE WRONG!
13018                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13019                 } else {
13020                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13021                 }
13022               break;
13023               
13024             default:
13025                 /* this should never happen */
13026                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13027                        "got unknown pointer type");
13028                 exit(1);
13029             }
13030             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13031             goto release ;
13032         }
13033         
13034         
13035         assert( 0 );
13036         /* just copy the pointers */
13037         size = AOP_SIZE(result);
13038         offset = 0 ;
13039         while (size--) {
13040             pic16_aopPut(AOP(result),
13041                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13042                    offset);
13043             offset++;
13044         }
13045         goto release ;
13046     }
13047     
13048
13049
13050     /* so we now know that the size of destination is greater
13051     than the size of the source.
13052     Now, if the next iCode is an operator then we might be
13053     able to optimize the operation without performing a cast.
13054     */
13055     if(genMixedOperation(ic))
13056       goto release;
13057
13058     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13059     
13060     /* we move to result for the size of source */
13061     size = AOP_SIZE(right);
13062     offset = 0 ;
13063
13064     while (size--) {
13065       if(!_G.resDirect)
13066         pic16_mov2f(AOP(result), AOP(right), offset);
13067       offset++;
13068     }
13069
13070     /* now depending on the sign of the destination */
13071     size = AOP_SIZE(result) - AOP_SIZE(right);
13072     /* if unsigned or not an integral type */
13073     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13074       while (size--)
13075         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13076     } else {
13077       /* we need to extend the sign :( */
13078
13079       if(size == 1) {
13080         /* Save one instruction of casting char to int */
13081         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13082         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13083         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13084       } else {
13085         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13086
13087         if(offset)
13088           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13089         else
13090           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13091         
13092         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13093
13094         while (size--)
13095           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13096       }
13097     }
13098
13099 release:
13100     pic16_freeAsmop(right,NULL,ic,TRUE);
13101     pic16_freeAsmop(result,NULL,ic,TRUE);
13102
13103 }
13104
13105 /*-----------------------------------------------------------------*/
13106 /* genDjnz - generate decrement & jump if not zero instrucion      */
13107 /*-----------------------------------------------------------------*/
13108 static int genDjnz (iCode *ic, iCode *ifx)
13109 {
13110     symbol *lbl, *lbl1;
13111     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13112
13113     if (!ifx)
13114         return 0;
13115     
13116     /* if the if condition has a false label
13117        then we cannot save */
13118     if (IC_FALSE(ifx))
13119         return 0;
13120
13121     /* if the minus is not of the form 
13122        a = a - 1 */
13123     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13124         !IS_OP_LITERAL(IC_RIGHT(ic)))
13125         return 0;
13126
13127     if (operandLitValue(IC_RIGHT(ic)) != 1)
13128         return 0;
13129
13130     /* if the size of this greater than one then no
13131        saving */
13132     if (getSize(operandType(IC_RESULT(ic))) > 1)
13133         return 0;
13134
13135     /* otherwise we can save BIG */
13136     lbl = newiTempLabel(NULL);
13137     lbl1= newiTempLabel(NULL);
13138
13139     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13140     
13141     if (IS_AOP_PREG(IC_RESULT(ic))) {
13142         pic16_emitcode("dec","%s",
13143                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13144         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13145         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13146     } else {    
13147
13148
13149       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13150       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13151
13152       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13153       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13154
13155     }
13156     
13157     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13158     ifx->generated = 1;
13159     return 1;
13160 }
13161
13162 /*-----------------------------------------------------------------*/
13163 /* genReceive - generate code for a receive iCode                  */
13164 /*-----------------------------------------------------------------*/
13165 static void genReceive (iCode *ic)
13166 {    
13167
13168   FENTRY;
13169
13170 #if 0
13171   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13172         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13173 #endif
13174 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13175
13176   if (isOperandInFarSpace(IC_RESULT(ic))
13177       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13178           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13179
13180     int size = getSize(operandType(IC_RESULT(ic)));
13181     int offset =  pic16_fReturnSizePic - size;
13182
13183       assert( 0 );
13184       while (size--) {
13185         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13186                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13187                       offset++;
13188         }
13189
13190       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13191
13192       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13193       size = AOP_SIZE(IC_RESULT(ic));
13194       offset = 0;
13195       while (size--) {
13196         pic16_emitcode ("pop","acc");
13197         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13198       }
13199   } else {
13200     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13201     _G.accInUse++;
13202     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13203     _G.accInUse--;
13204
13205     /* set pseudo stack pointer to where it should be - dw*/
13206     GpsuedoStkPtr = ic->parmBytes;
13207
13208     /* setting GpsuedoStkPtr has side effects here: */
13209     assignResultValue(IC_RESULT(ic), 0);
13210   }
13211
13212   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13213 }
13214
13215 /*-----------------------------------------------------------------*/
13216 /* genDummyRead - generate code for dummy read of volatiles        */
13217 /*-----------------------------------------------------------------*/
13218 static void
13219 genDummyRead (iCode * ic)
13220 {
13221   operand *op;
13222   int i;
13223
13224   op = IC_RIGHT(ic);
13225   if (op && IS_SYMOP(op)) {
13226     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13227       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13228       return;
13229     }
13230     pic16_aopOp (op, ic, FALSE);
13231     for (i=0; i < AOP_SIZE(op); i++) {
13232       // may need to protect this from the peepholer -- this is not nice but works...
13233       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13234       pic16_mov2w (AOP(op),i);
13235       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13236     } // for i
13237     pic16_freeAsmop (op, NULL, ic, TRUE);
13238   } else if (op) {
13239     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13240   } // if
13241 }
13242
13243 /*-----------------------------------------------------------------*/
13244 /* genpic16Code - generate code for pic16 based controllers        */
13245 /*-----------------------------------------------------------------*/
13246 /*
13247  * At this point, ralloc.c has gone through the iCode and attempted
13248  * to optimize in a way suitable for a PIC. Now we've got to generate
13249  * PIC instructions that correspond to the iCode.
13250  *
13251  * Once the instructions are generated, we'll pass through both the
13252  * peep hole optimizer and the pCode optimizer.
13253  *-----------------------------------------------------------------*/
13254
13255 void genpic16Code (iCode *lic)
13256 {
13257   iCode *ic;
13258   int cln = 0;
13259
13260     lineHead = lineCurr = NULL;
13261
13262     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13263     pic16_addpBlock(pb);
13264
13265 #if 0
13266     /* if debug information required */
13267     if (options.debug && currFunc) {
13268       if (currFunc) {
13269         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13270       }
13271     }
13272 #endif
13273
13274     for (ic = lic ; ic ; ic = ic->next ) {
13275
13276       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13277       if ( cln != ic->lineno ) {
13278         if ( options.debug ) {
13279           debugFile->writeCLine (ic);
13280         }
13281         
13282         if(!options.noCcodeInAsm) {
13283           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13284               printCLine(ic->filename, ic->lineno)));
13285         }
13286
13287         cln = ic->lineno ;
13288       }
13289         
13290       if(options.iCodeInAsm) {
13291         char *l;
13292
13293           /* insert here code to print iCode as comment */
13294           l = Safe_strdup(printILine(ic));
13295           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13296       }
13297
13298       /* if the result is marked as
13299        * spilt and rematerializable or code for
13300        * this has already been generated then
13301        * do nothing */
13302       if (resultRemat(ic) || ic->generated ) 
13303         continue ;
13304         
13305       /* depending on the operation */
13306       switch (ic->op) {
13307         case '!' :
13308           pic16_genNot(ic);
13309           break;
13310             
13311         case '~' :
13312           pic16_genCpl(ic);
13313           break;
13314             
13315         case UNARYMINUS:
13316           genUminus (ic);
13317           break;
13318             
13319         case IPUSH:
13320           genIpush (ic);
13321           break;
13322             
13323         case IPOP:
13324           /* IPOP happens only when trying to restore a 
13325            * spilt live range, if there is an ifx statement
13326            * following this pop then the if statement might
13327            * be using some of the registers being popped which
13328            * would destroy the contents of the register so
13329            * we need to check for this condition and handle it */
13330            if (ic->next
13331              && ic->next->op == IFX
13332              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13333                genIfx (ic->next,ic);
13334           else
13335             genIpop (ic);
13336           break; 
13337             
13338         case CALL:
13339           genCall (ic);
13340           break;
13341             
13342         case PCALL:
13343           genPcall (ic);
13344           break;
13345             
13346         case FUNCTION:
13347           genFunction (ic);
13348           break;
13349             
13350         case ENDFUNCTION:
13351           genEndFunction (ic);
13352           break;
13353             
13354         case RETURN:
13355           genRet (ic);
13356           break;
13357             
13358         case LABEL:
13359           genLabel (ic);
13360           break;
13361             
13362         case GOTO:
13363           genGoto (ic);
13364           break;
13365             
13366         case '+' :
13367           pic16_genPlus (ic) ;
13368           break;
13369             
13370         case '-' :
13371           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13372             pic16_genMinus (ic);
13373           break;
13374
13375         case '*' :
13376           genMult (ic);
13377           break;
13378             
13379         case '/' :
13380           genDiv (ic) ;
13381           break;
13382             
13383         case '%' :
13384           genMod (ic);
13385           break;
13386             
13387         case '>' :
13388           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13389           break;
13390             
13391         case '<' :
13392           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13393           break;
13394             
13395         case LE_OP:
13396         case GE_OP:
13397         case NE_OP:
13398           /* note these two are xlated by algebraic equivalence
13399            * during parsing SDCC.y */
13400           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13401             "got '>=' or '<=' shouldn't have come here");
13402           break;
13403
13404         case EQ_OP:
13405           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13406           break;            
13407             
13408         case AND_OP:
13409           genAndOp (ic);
13410           break;
13411             
13412         case OR_OP:
13413           genOrOp (ic);
13414           break;
13415             
13416         case '^' :
13417           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13418           break;
13419             
13420         case '|' :
13421           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13422           break;
13423             
13424         case BITWISEAND:
13425           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13426           break;
13427             
13428         case INLINEASM:
13429           genInline (ic);
13430           break;
13431             
13432         case RRC:
13433           genRRC (ic);
13434           break;
13435             
13436         case RLC:
13437           genRLC (ic);
13438           break;
13439             
13440         case GETHBIT:
13441           genGetHbit (ic);
13442           break;
13443             
13444         case LEFT_OP:
13445           genLeftShift (ic);
13446           break;
13447             
13448         case RIGHT_OP:
13449           genRightShift (ic);
13450           break;
13451             
13452         case GET_VALUE_AT_ADDRESS:
13453           genPointerGet(ic);
13454           break;
13455             
13456         case '=' :
13457           if (POINTER_SET(ic))
13458             genPointerSet(ic);
13459           else
13460             genAssign(ic);
13461           break;
13462             
13463         case IFX:
13464           genIfx (ic,NULL);
13465           break;
13466             
13467         case ADDRESS_OF:
13468           genAddrOf (ic);
13469           break;
13470             
13471         case JUMPTABLE:
13472           genJumpTab (ic);
13473           break;
13474             
13475         case CAST:
13476           genCast (ic);
13477           break;
13478             
13479         case RECEIVE:
13480           genReceive(ic);
13481           break;
13482             
13483         case SEND:
13484           addSet(&_G.sendSet,ic);
13485           break;
13486
13487         case DUMMY_READ_VOLATILE:
13488           genDummyRead (ic);
13489           break;
13490
13491         default :
13492           ic = ic;
13493       }
13494     }
13495
13496
13497     /* now we are ready to call the
13498        peep hole optimizer */
13499     if (!options.nopeep)
13500       peepHole (&lineHead);
13501
13502     /* now do the actual printing */
13503     printLine (lineHead, codeOutFile);
13504
13505 #ifdef PCODE_DEBUG
13506     DFPRINTF((stderr,"printing pBlock\n\n"));
13507     pic16_printpBlock(stdout,pb);
13508 #endif
13509
13510     return;
13511 }
13512