* src/pic16/device.h (struct pic16_options_t): added 'int CATregs' flag
[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, *fntype;
3402   int stackParms=0;
3403   symbol *retlbl = newiTempLabel(NULL);
3404   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3405   
3406     FENTRY;
3407
3408     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3409     fntype = operandType( IC_LEFT(ic) )->next;
3410
3411     /* if send set is not empty the assign */
3412     if (_G.sendSet) {
3413       iCode *sic;
3414       int psuedoStkPtr=-1; 
3415
3416       /* reverse sendSet if function is not reentrant */
3417       if(!IFFUNC_ISREENT(fntype))
3418         _G.sendSet = reverseSet(_G.sendSet);
3419
3420       stackParms = 0;
3421       
3422       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3423         int size;
3424
3425           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3426           size = AOP_SIZE(IC_LEFT(sic));
3427           stackParms += size;
3428
3429           /* all parameters are passed via stack, since WREG is clobbered
3430            * by the calling sequence */
3431           while (size--) {
3432             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3433             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3434             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3435
3436             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3437             pushw();
3438           }
3439
3440           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3441       }
3442
3443       _G.stackRegSet = _G.sendSet;
3444       _G.sendSet = NULL;
3445     }
3446
3447     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3448
3449     // push return address
3450     // push $ on return stack, then replace with retlbl
3451
3452     /* Thanks to Thorsten Klose for pointing out that the following
3453      * snippet should be interrupt safe */
3454     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3455     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3456
3457     pic16_emitpcodeNULLop(POC_PUSH);
3458
3459     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3460     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3461     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3462     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3463     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3465
3466
3467     /* restore interrupt control register */
3468     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3469     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3470
3471     /* make the call by writing the pointer into pc */
3472     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3473     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3474
3475     // note: MOVFF to PCL not allowed
3476     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3477     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3478
3479
3480     /* return address is here: (X) */
3481     pic16_emitpLabelFORCE(retlbl->key);
3482
3483     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3484
3485     GpsuedoStkPtr=0;
3486     /* if we need assign a result value */
3487     if ((IS_ITEMP(IC_RESULT(ic))
3488           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3489               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3490         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3491
3492       _G.accInUse++;
3493       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3494       _G.accInUse--;
3495
3496       assignResultValue(IC_RESULT(ic), 1);
3497
3498       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3500                 
3501       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3502     }
3503
3504 //    stackParms -= use_wreg;
3505     
3506     if(stackParms>0) {
3507       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3508       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3509       if(STACK_MODEL_LARGE) {
3510         emitSKPNC;
3511         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3512       }
3513     }
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* resultRemat - result  is rematerializable                       */
3518 /*-----------------------------------------------------------------*/
3519 static int resultRemat (iCode *ic)
3520 {
3521   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3522   if (SKIP_IC(ic) || ic->op == IFX)
3523     return 0;
3524
3525   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3526     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3527     if (sym->remat && !POINTER_SET(ic)) 
3528       return 1;
3529   }
3530
3531   return 0;
3532 }
3533
3534 #if defined(__BORLANDC__) || defined(_MSC_VER)
3535 #define STRCASECMP stricmp
3536 #else
3537 #define STRCASECMP strcasecmp
3538 #endif
3539
3540 #if 0
3541 /*-----------------------------------------------------------------*/
3542 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3543 /*-----------------------------------------------------------------*/
3544 static bool inExcludeList(char *s)
3545 {
3546   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3547     int i =0;
3548     
3549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3550     if (options.excludeRegs[i] &&
3551     STRCASECMP(options.excludeRegs[i],"none") == 0)
3552         return FALSE ;
3553
3554     for ( i = 0 ; options.excludeRegs[i]; i++) {
3555         if (options.excludeRegs[i] &&
3556         STRCASECMP(s,options.excludeRegs[i]) == 0)
3557             return TRUE;
3558     }
3559     return FALSE ;
3560 }
3561 #endif
3562
3563 /*-----------------------------------------------------------------*/
3564 /* genFunction - generated code for function entry                 */
3565 /*-----------------------------------------------------------------*/
3566 static void genFunction (iCode *ic)
3567 {
3568   symbol *sym;
3569   sym_link *ftype;
3570   
3571     FENTRY;
3572     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3573
3574     pic16_labelOffset += (max_key+4);
3575     max_key=0;
3576     GpsuedoStkPtr=0;
3577     _G.nRegsSaved = 0;
3578         
3579     ftype = operandType(IC_LEFT(ic));
3580     sym = OP_SYMBOL(IC_LEFT(ic));
3581
3582     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3583       /* create an absolute section at the interrupt vector:
3584        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3585       symbol *asym;
3586       char asymname[128];
3587       pBlock *apb;
3588
3589 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3590
3591         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3592           sprintf(asymname, "ivec_%s", sym->name);
3593         else
3594           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3595   
3596         /* when an interrupt is declared as naked, do not emit the special
3597          * wrapper segment at vector address. The user should take care for
3598          * this instead. -- VR */
3599
3600         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3601           asym = newSymbol(asymname, 0);
3602           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3603           pic16_addpBlock( apb );
3604
3605           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3606           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3607           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3608           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3609           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3610                 
3611           /* mark the end of this tiny function */
3612           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3613         } else {
3614           sprintf(asymname, "%s", sym->rname);
3615         }
3616
3617         {
3618           absSym *abSym;
3619
3620             abSym = Safe_calloc(1, sizeof(absSym));
3621             strcpy(abSym->name, asymname);
3622
3623             switch( FUNC_INTNO(sym->type) ) {
3624               case 0: abSym->address = 0x000000; break;
3625               case 1: abSym->address = 0x000008; break;
3626               case 2: abSym->address = 0x000018; break;
3627               
3628               default:
3629 //                fprintf(stderr, "no interrupt number is given\n");
3630                 abSym->address = -1; break;
3631             }
3632
3633             /* relocate interrupt vectors if needed */
3634             if(abSym->address != -1)
3635               abSym->address += pic16_options.ivt_loc;
3636
3637             addSet(&absSymSet, abSym);
3638         }
3639     }
3640
3641     /* create the function header */
3642     pic16_emitcode(";","-----------------------------------------");
3643     pic16_emitcode(";"," function %s",sym->name);
3644     pic16_emitcode(";","-----------------------------------------");
3645
3646     pic16_emitcode("","%s:",sym->rname);
3647     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3648
3649     {
3650       absSym *ab;
3651
3652         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3653           if(!strcmp(ab->name, sym->rname)) {
3654             pic16_pBlockConvert2Absolute(pb);
3655             break;
3656           }
3657         }
3658     }
3659
3660     if(IFFUNC_ISNAKED(ftype)) {
3661       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3662       return;
3663     }
3664         
3665     /* if critical function then turn interrupts off */
3666     if (IFFUNC_ISCRITICAL(ftype)) {
3667       //pic16_emitcode("clr","ea");
3668     }
3669
3670     currFunc = sym;             /* update the currFunc symbol */
3671     _G.fregsUsed = sym->regsUsed;
3672     _G.sregsAlloc = newBitVect(128);
3673     
3674
3675     /* if this is an interrupt service routine then
3676      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3677     if (IFFUNC_ISISR(sym->type)) {
3678         _G.usefastretfie = 1;   /* use shadow registers by default */
3679         
3680         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3681         if(!FUNC_ISSHADOWREGS(sym->type)) {
3682           /* do not save WREG,STATUS,BSR for high priority interrupts
3683            * because they are stored in the hardware shadow registers already */
3684           _G.usefastretfie = 0;
3685           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3686           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3687           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3688         }
3689
3690         /* these should really be optimized somehow, because not all
3691          * interrupt handlers modify them */
3692         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3693         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3694         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3695         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3696         
3697 //        pic16_pBlockConvert2ISR(pb);
3698     }
3699
3700     /* emit code to setup stack frame if user enabled,
3701      * and function is not main() */
3702     
3703 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3704     if(strcmp(sym->name, "main")) {
3705       if(0 
3706         || !options.ommitFramePtr 
3707 //        || sym->regsUsed
3708         || IFFUNC_ARGS(sym->type)
3709         || FUNC_HASSTACKPARM(sym->etype)
3710         ) {
3711         /* setup the stack frame */
3712         if(STACK_MODEL_LARGE)
3713           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3714         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3715
3716         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3717         if(STACK_MODEL_LARGE)
3718           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3719       }
3720     }
3721
3722     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3723           && sym->stack) {
3724
3725       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3726
3727       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3728       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3729       emitSKPC;
3730       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3731     }
3732           
3733     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3734       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3735         _G.useWreg = 0;
3736       else
3737         _G.useWreg = 1;
3738     } else
3739       _G.useWreg = 0;
3740
3741     /* if callee-save to be used for this function
3742      * then save the registers being used in this function */
3743 //    if (IFFUNC_CALLEESAVES(sym->type))
3744     if(strcmp(sym->name, "main")) {
3745       int i;
3746
3747         /* if any registers used */
3748         if (sym->regsUsed) {
3749           /* save the registers used */
3750           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3751           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3752           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3753             if (bitVectBitValue(sym->regsUsed,i)) {
3754               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3755               _G.nRegsSaved++;
3756
3757               if(!pic16_regWithIdx(i)->wasUsed) {
3758                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3759                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3760                 pic16_regWithIdx(i)->wasUsed = 1;
3761               }
3762             }
3763           }
3764           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3765         }
3766     }
3767         
3768     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3769 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3770 }
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genEndFunction - generates epilogue for functions               */
3774 /*-----------------------------------------------------------------*/
3775 static void genEndFunction (iCode *ic)
3776 {
3777   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3778
3779     FENTRY;
3780
3781     if(IFFUNC_ISNAKED(sym->type)) {
3782       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3783       return;
3784     }
3785
3786     _G.stack_lat = 0;
3787
3788     /* add code for ISCRITICAL */
3789     if(IFFUNC_ISCRITICAL(sym->type)) {
3790       /* if critical function, turn on interrupts */
3791       
3792       /* TODO: add code here -- VR */
3793     }
3794     
3795 //    sym->regsUsed = _G.fregsUsed;
3796     
3797     /* now we need to restore the registers */
3798     /* if any registers used */
3799
3800     /* first restore registers that might be used for stack access */
3801     if(_G.sregsAllocSet) {
3802     regs *sr;
3803     
3804       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3805       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3806         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3807       }
3808     }
3809
3810     if (strcmp(sym->name, "main") && sym->regsUsed) {
3811       int i;
3812
3813         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3814         /* restore registers used */
3815         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3816         for ( i = sym->regsUsed->size; i >= 0; i--) {
3817           if (bitVectBitValue(sym->regsUsed,i)) {
3818             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3819             _G.nRegsSaved--;
3820           }
3821         }
3822         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3823     }
3824
3825       
3826
3827     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3828           && sym->stack) {
3829       if (sym->stack == 1) {
3830         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3831         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3832       } else {
3833         // we have to add more than one...
3834         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3835         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3836         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3837         emitSKPNC;
3838         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3839         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3840         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3841       }
3842     }
3843
3844     if(strcmp(sym->name, "main")) {
3845       if(0
3846         || !options.ommitFramePtr
3847 //        || sym->regsUsed
3848         || IFFUNC_ARGS(sym->type)
3849         || FUNC_HASSTACKPARM(sym->etype)
3850         ) {
3851         /* restore stack frame */
3852         if(STACK_MODEL_LARGE)
3853           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3854         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3855       }
3856     }
3857
3858     _G.useWreg = 0;
3859
3860     if (IFFUNC_ISISR(sym->type)) {
3861       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3862       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3863       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3864       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3865
3866       if(!FUNC_ISSHADOWREGS(sym->type)) {
3867         /* do not restore interrupt vector for WREG,STATUS,BSR
3868          * for high priority interrupt, see genFunction */
3869         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3870         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3871         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3872       }
3873 //      _G.interruptvector = 0;         /* sanity check */
3874
3875
3876       /* if debug then send end of function */
3877 /*      if (options.debug && currFunc)  */
3878       if (currFunc) {
3879         debugFile->writeEndFunction (currFunc, ic, 1);
3880       }
3881         
3882       if(_G.usefastretfie)
3883         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3884       else
3885         pic16_emitpcodeNULLop(POC_RETFIE);
3886
3887       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3888       
3889       _G.usefastretfie = 0;
3890       return;
3891     }
3892
3893     if (IFFUNC_ISCRITICAL(sym->type)) {
3894       pic16_emitcode("setb","ea");
3895     }
3896
3897     /* if debug then send end of function */
3898     if (currFunc) {
3899       debugFile->writeEndFunction (currFunc, ic, 1);
3900     }
3901
3902     /* insert code to restore stack frame, if user enabled it
3903      * and function is not main() */
3904          
3905
3906     pic16_emitpcodeNULLop(POC_RETURN);
3907
3908     /* Mark the end of a function */
3909     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3910 }
3911
3912
3913 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3914 {
3915   unsigned long lit=1;
3916   operand *op;
3917
3918     op = IC_LEFT(ic);
3919   
3920     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3921     if(AOP_TYPE(op) == AOP_LIT) {
3922       if(!IS_FLOAT(operandType( op ))) {
3923         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3924       } else {
3925         union {
3926           unsigned long lit_int;
3927           float lit_float;
3928         } info;
3929         
3930         /* take care if literal is a float */
3931         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3932         lit = info.lit_int;
3933       }
3934     }
3935
3936     if(is_LitOp(op)) {
3937       pic16_movLit2f(dest, lit);
3938     } else {
3939       if(dest->type == PO_WREG && (offset == 0)) {
3940         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3941       return;
3942     }
3943     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3944   }
3945 }
3946
3947 /*-----------------------------------------------------------------*/
3948 /* genRet - generate code for return statement                     */
3949 /*-----------------------------------------------------------------*/
3950 static void genRet (iCode *ic)
3951 {
3952   int size;
3953   operand *left;
3954
3955     FENTRY;
3956         /* if we have no return value then
3957          * just generate the "ret" */
3958         
3959         if (!IC_LEFT(ic)) 
3960                 goto jumpret;       
3961     
3962         /* we have something to return then
3963          * move the return value into place */
3964         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3965         size = AOP_SIZE(IC_LEFT(ic));
3966
3967         if(size <= 4) {
3968           if(size>3)
3969             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3970           
3971           if(size>2)
3972             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3973
3974           if(size>1)
3975             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3976           
3977           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3978
3979         } else {
3980                 /* >32-bits, setup stack and FSR0 */
3981                 while (size--) {
3982 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3983 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3984
3985                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3986
3987 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3988                         GpsuedoStkPtr++;
3989                 }
3990                         
3991                 /* setup FSR0 */
3992                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3993                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3994
3995                 if(STACK_MODEL_LARGE) {
3996                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3997                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3998                 } else {
3999                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4000                 }
4001         }
4002                                 
4003 #if 0
4004         /* old code, left here for reference -- VR */    
4005         while (size--) {
4006           char *l ;
4007
4008                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4009                         /* #NOCHANGE */
4010                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4011                         pic16_emitpcomment("push %s",l);
4012                         pushed++;
4013                 } else {
4014                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4015                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4016                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4017                         
4018                         if (strcmp(fReturn[offset],l)) {
4019                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4020                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4021                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4022                                 } else {
4023                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4024                                 }
4025                                 
4026                                 if(size) {
4027                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4028                                 }
4029                                 offset++;
4030                         }
4031                 }
4032         }    
4033
4034         if (pushed) {
4035                 while(pushed) {
4036                         pushed--;
4037                         if (strcmp(fReturn[pushed],"a"))
4038                                 pic16_emitcode("pop",fReturn[pushed]);
4039                         else
4040                                 pic16_emitcode("pop","acc");
4041                 }
4042         }
4043 #endif
4044
4045
4046         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4047     
4048 jumpret:
4049         /* generate a jump to the return label
4050          * if the next is not the return statement */
4051         if (!(ic->next && ic->next->op == LABEL
4052                 && IC_LABEL(ic->next) == returnLabel)) {
4053         
4054                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4055                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4056         }
4057 }
4058
4059 /*-----------------------------------------------------------------*/
4060 /* genLabel - generates a label                                    */
4061 /*-----------------------------------------------------------------*/
4062 static void genLabel (iCode *ic)
4063 {
4064   FENTRY;
4065
4066   /* special case never generate */
4067   if (IC_LABEL(ic) == entryLabel)
4068     return ;
4069
4070   pic16_emitpLabel(IC_LABEL(ic)->key);
4071 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4072 }
4073
4074 /*-----------------------------------------------------------------*/
4075 /* genGoto - generates a goto                                      */
4076 /*-----------------------------------------------------------------*/
4077 //tsd
4078 static void genGoto (iCode *ic)
4079 {
4080   FENTRY;
4081   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4082 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4083 }
4084
4085
4086 /*-----------------------------------------------------------------*/
4087 /* genMultbits :- multiplication of bits                           */
4088 /*-----------------------------------------------------------------*/
4089 static void genMultbits (operand *left, 
4090                          operand *right, 
4091                          operand *result)
4092 {
4093   FENTRY;
4094
4095   if(!pic16_sameRegs(AOP(result),AOP(right)))
4096     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4097
4098   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4099   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4100   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4101
4102 }
4103
4104
4105 /*-----------------------------------------------------------------*/
4106 /* genMultOneByte : 8 bit multiplication & division                */
4107 /*-----------------------------------------------------------------*/
4108 static void genMultOneByte (operand *left,
4109                             operand *right,
4110                             operand *result)
4111 {
4112
4113   FENTRY;
4114   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4115   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4116
4117   /* (if two literals, the value is computed before) */
4118   /* if one literal, literal on the right */
4119   if (AOP_TYPE(left) == AOP_LIT){
4120     operand *t = right;
4121     right = left;
4122     left = t;
4123   }
4124
4125         /* size is already checked in genMult == 1 */
4126 //      size = AOP_SIZE(result);
4127
4128         if (AOP_TYPE(right) == AOP_LIT){
4129                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4130                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4131                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4132                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4133         } else {
4134                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4135                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4136                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4137                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4138         }
4139         
4140         pic16_genMult8X8_8 (left, right,result);
4141 }
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genMultOneWord : 16 bit multiplication                          */
4145 /*-----------------------------------------------------------------*/
4146 static void genMultOneWord (operand *left,
4147                             operand *right,
4148                             operand *result)
4149 {
4150   FENTRY;
4151   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4152   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4153
4154   /* (if two literals, the value is computed before)
4155    * if one literal, literal on the right */
4156   if (AOP_TYPE(left) == AOP_LIT){
4157     operand *t = right;
4158     right = left;
4159     left = t;
4160   }
4161
4162   /* size is checked already == 2 */
4163 //  size = AOP_SIZE(result);
4164
4165   if (AOP_TYPE(right) == AOP_LIT) {
4166     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4167       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4168       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4169       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4170   } else {
4171     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4172       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4173       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4174       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4175   }
4176         
4177   pic16_genMult16X16_16(left, right,result);
4178 }
4179
4180 /*-----------------------------------------------------------------*/
4181 /* genMultOneLong : 32 bit multiplication                          */
4182 /*-----------------------------------------------------------------*/
4183 static void genMultOneLong (operand *left,
4184                             operand *right,
4185                             operand *result)
4186 {
4187   FENTRY;
4188   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4189   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4190
4191   /* (if two literals, the value is computed before)
4192    * if one literal, literal on the right */
4193   if (AOP_TYPE(left) == AOP_LIT){
4194     operand *t = right;
4195     right = left;
4196     left = t;
4197   }
4198
4199   /* size is checked already == 4 */
4200 //  size = AOP_SIZE(result);
4201
4202   if (AOP_TYPE(right) == AOP_LIT) {
4203     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4204         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4205         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4206         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4207   } else {
4208     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4209         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4210         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4211         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212   }
4213         
4214   pic16_genMult32X32_32(left, right,result);
4215 }
4216
4217
4218
4219 /*-----------------------------------------------------------------*/
4220 /* genMult - generates code for multiplication                     */
4221 /*-----------------------------------------------------------------*/
4222 static void genMult (iCode *ic)
4223 {
4224   operand *left = IC_LEFT(ic);
4225   operand *right = IC_RIGHT(ic);
4226   operand *result= IC_RESULT(ic);   
4227
4228     FENTRY;
4229         /* assign the amsops */
4230         pic16_aopOp (left,ic,FALSE);
4231         pic16_aopOp (right,ic,FALSE);
4232         pic16_aopOp (result,ic,TRUE);
4233
4234         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4235
4236         /* special cases first *
4237         * both are bits */
4238         if (AOP_TYPE(left) == AOP_CRY
4239                 && AOP_TYPE(right)== AOP_CRY) {
4240                 genMultbits(left,right,result);
4241           goto release ;
4242         }
4243
4244         /* if both are of size == 1 */
4245         if(AOP_SIZE(left) == 1
4246                 && AOP_SIZE(right) == 1) {
4247                 genMultOneByte(left,right,result);
4248           goto release ;
4249         }
4250
4251         /* if both are of size == 2 */
4252         if(AOP_SIZE(left) == 2
4253                 && AOP_SIZE(right) == 2) {
4254                 genMultOneWord(left, right, result);
4255           goto release;
4256         }
4257         
4258         /* if both are of size == 4 */
4259         if(AOP_SIZE(left) == 4
4260                 && AOP_SIZE(right) == 4) {
4261                 genMultOneLong(left, right, result);
4262           goto release;
4263         }
4264         
4265         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4266
4267
4268         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4269         /* should have been converted to function call */
4270         assert(0) ;
4271
4272 release :
4273         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4274         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4275         pic16_freeAsmop(result,NULL,ic,TRUE); 
4276 }
4277
4278 /*-----------------------------------------------------------------*/
4279 /* genDivbits :- division of bits                                  */
4280 /*-----------------------------------------------------------------*/
4281 static void genDivbits (operand *left, 
4282                         operand *right, 
4283                         operand *result)
4284 {
4285   char *l;
4286
4287     FENTRY;
4288     /* the result must be bit */    
4289     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4290     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4291
4292     MOVA(l);    
4293
4294     pic16_emitcode("div","ab");
4295     pic16_emitcode("rrc","a");
4296     pic16_aopPut(AOP(result),"c",0);
4297 }
4298
4299 /*-----------------------------------------------------------------*/
4300 /* genDivOneByte : 8 bit division                                  */
4301 /*-----------------------------------------------------------------*/
4302 static void genDivOneByte (operand *left,
4303                            operand *right,
4304                            operand *result)
4305 {
4306   sym_link *opetype = operandType(result);
4307   char *l ;
4308   symbol *lbl ;
4309   int size,offset;
4310
4311         /* result = divident / divisor
4312          * - divident may be a register or a literal,
4313          * - divisor may be a register or a literal,
4314          * so there are 3 cases (literal / literal is optimized
4315          * by the front-end) to handle.
4316          * In addition we must handle signed and unsigned, which
4317          * result in 6 final different cases -- VR */
4318
4319     FENTRY;
4320     
4321     size = AOP_SIZE(result) - 1;
4322     offset = 1;
4323     /* signed or unsigned */
4324     if (SPEC_USIGN(opetype)) {
4325       pCodeOp *pct1,    /* count */
4326                 *pct2,  /* reste */
4327                 *pct3;  /* temp */
4328       symbol *label1, *label2, *label3;;
4329
4330
4331         /* unsigned is easy */
4332
4333         pct1 = pic16_popGetTempReg(1);
4334         pct2 = pic16_popGetTempReg(1);
4335         pct3 = pic16_popGetTempReg(1);
4336         
4337         label1 = newiTempLabel(NULL);
4338         label2 = newiTempLabel(NULL);
4339         label3 = newiTempLabel(NULL);
4340
4341         /* the following algorithm is extracted from divuint.c */
4342
4343         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4344         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4345         
4346         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4347
4348         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4349         
4350         pic16_emitpLabel(label1->key);
4351         
4352         emitCLRC;
4353         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4354
4355
4356         emitCLRC;
4357         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4358         
4359
4360         emitSKPNC;
4361         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4362         
4363         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4364         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4365         
4366         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4367         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4368         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4369         
4370         pic16_emitpLabel( label3->key );
4371         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4372         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4373         
4374         
4375
4376         pic16_emitpLabel(label2->key);
4377         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4378         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4379         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4380         
4381         /* result is in wreg */
4382         if(AOP_TYPE(result) != AOP_ACC)
4383                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4384
4385         pic16_popReleaseTempReg( pct3, 1);
4386         pic16_popReleaseTempReg( pct2, 1);
4387         pic16_popReleaseTempReg( pct1, 1);
4388
4389         return ;
4390     }
4391
4392     /* signed is a little bit more difficult */
4393
4394     /* save the signs of the operands */
4395     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4396     MOVA(l);    
4397     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4398     pic16_emitcode("push","acc"); /* save it on the stack */
4399
4400     /* now sign adjust for both left & right */
4401     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4402     MOVA(l);       
4403     lbl = newiTempLabel(NULL);
4404     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4405     pic16_emitcode("cpl","a");   
4406     pic16_emitcode("inc","a");
4407     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4408     pic16_emitcode("mov","b,a");
4409
4410     /* sign adjust left side */
4411     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4412     MOVA(l);
4413
4414     lbl = newiTempLabel(NULL);
4415     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4416     pic16_emitcode("cpl","a");
4417     pic16_emitcode("inc","a");
4418     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4419
4420     /* now the division */
4421     pic16_emitcode("div","ab");
4422     /* we are interested in the lower order
4423     only */
4424     pic16_emitcode("mov","b,a");
4425     lbl = newiTempLabel(NULL);
4426     pic16_emitcode("pop","acc");   
4427     /* if there was an over flow we don't 
4428     adjust the sign of the result */
4429     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4430     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4431     CLRC;
4432     pic16_emitcode("clr","a");
4433     pic16_emitcode("subb","a,b");
4434     pic16_emitcode("mov","b,a");
4435     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4436
4437     /* now we are done */
4438     pic16_aopPut(AOP(result),"b",0);
4439     if(size > 0){
4440         pic16_emitcode("mov","c,b.7");
4441         pic16_emitcode("subb","a,acc");   
4442     }
4443     while (size--)
4444         pic16_aopPut(AOP(result),"a",offset++);
4445
4446 }
4447
4448 /*-----------------------------------------------------------------*/
4449 /* genDiv - generates code for division                            */
4450 /*-----------------------------------------------------------------*/
4451 static void genDiv (iCode *ic)
4452 {
4453     operand *left = IC_LEFT(ic);
4454     operand *right = IC_RIGHT(ic);
4455     operand *result= IC_RESULT(ic);   
4456
4457
4458         /* Division is a very lengthy algorithm, so it is better
4459          * to call support routines than inlining algorithm.
4460          * Division functions written here just in case someone
4461          * wants to inline and not use the support libraries -- VR */
4462
4463     FENTRY;
4464     
4465     /* assign the amsops */
4466     pic16_aopOp (left,ic,FALSE);
4467     pic16_aopOp (right,ic,FALSE);
4468     pic16_aopOp (result,ic,TRUE);
4469
4470     /* special cases first */
4471     /* both are bits */
4472     if (AOP_TYPE(left) == AOP_CRY &&
4473         AOP_TYPE(right)== AOP_CRY) {
4474         genDivbits(left,right,result);
4475         goto release ;
4476     }
4477
4478     /* if both are of size == 1 */
4479     if (AOP_SIZE(left) == 1 &&
4480         AOP_SIZE(right) == 1 ) {
4481         genDivOneByte(left,right,result);
4482         goto release ;
4483     }
4484
4485     /* should have been converted to function call */
4486     assert(0);
4487 release :
4488     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4489     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4490     pic16_freeAsmop(result,NULL,ic,TRUE); 
4491 }
4492
4493 /*-----------------------------------------------------------------*/
4494 /* genModbits :- modulus of bits                                   */
4495 /*-----------------------------------------------------------------*/
4496 static void genModbits (operand *left, 
4497                         operand *right, 
4498                         operand *result)
4499 {
4500   char *l;
4501
4502     FENTRY;  
4503     
4504     werror(W_POSSBUG2, __FILE__, __LINE__);
4505     /* the result must be bit */    
4506     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4507     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4508
4509     MOVA(l);       
4510
4511     pic16_emitcode("div","ab");
4512     pic16_emitcode("mov","a,b");
4513     pic16_emitcode("rrc","a");
4514     pic16_aopPut(AOP(result),"c",0);
4515 }
4516
4517 /*-----------------------------------------------------------------*/
4518 /* genModOneByte : 8 bit modulus                                   */
4519 /*-----------------------------------------------------------------*/
4520 static void genModOneByte (operand *left,
4521                            operand *right,
4522                            operand *result)
4523 {
4524   sym_link *opetype = operandType(result);
4525   char *l ;
4526   symbol *lbl ;
4527
4528     FENTRY;
4529     werror(W_POSSBUG2, __FILE__, __LINE__);
4530
4531     /* signed or unsigned */
4532     if (SPEC_USIGN(opetype)) {
4533         /* unsigned is easy */
4534         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4535         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4536         MOVA(l);    
4537         pic16_emitcode("div","ab");
4538         pic16_aopPut(AOP(result),"b",0);
4539         return ;
4540     }
4541
4542     /* signed is a little bit more difficult */
4543
4544     /* save the signs of the operands */
4545     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4546     MOVA(l);
4547
4548     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4549     pic16_emitcode("push","acc"); /* save it on the stack */
4550
4551     /* now sign adjust for both left & right */
4552     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4553     MOVA(l);
4554
4555     lbl = newiTempLabel(NULL);
4556     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4557     pic16_emitcode("cpl","a");   
4558     pic16_emitcode("inc","a");
4559     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4560     pic16_emitcode("mov","b,a"); 
4561
4562     /* sign adjust left side */
4563     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4564     MOVA(l);
4565
4566     lbl = newiTempLabel(NULL);
4567     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4568     pic16_emitcode("cpl","a");   
4569     pic16_emitcode("inc","a");
4570     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4571
4572     /* now the multiplication */
4573     pic16_emitcode("div","ab");
4574     /* we are interested in the lower order
4575     only */
4576     lbl = newiTempLabel(NULL);
4577     pic16_emitcode("pop","acc");   
4578     /* if there was an over flow we don't 
4579     adjust the sign of the result */
4580     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4581     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4582     CLRC ;
4583     pic16_emitcode("clr","a");
4584     pic16_emitcode("subb","a,b");
4585     pic16_emitcode("mov","b,a");
4586     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4587
4588     /* now we are done */
4589     pic16_aopPut(AOP(result),"b",0);
4590
4591 }
4592
4593 /*-----------------------------------------------------------------*/
4594 /* genMod - generates code for division                            */
4595 /*-----------------------------------------------------------------*/
4596 static void genMod (iCode *ic)
4597 {
4598   operand *left = IC_LEFT(ic);
4599   operand *right = IC_RIGHT(ic);
4600   operand *result= IC_RESULT(ic);  
4601
4602     FENTRY;
4603     
4604     /* assign the amsops */
4605     pic16_aopOp (left,ic,FALSE);
4606     pic16_aopOp (right,ic,FALSE);
4607     pic16_aopOp (result,ic,TRUE);
4608
4609     /* special cases first */
4610     /* both are bits */
4611     if (AOP_TYPE(left) == AOP_CRY &&
4612         AOP_TYPE(right)== AOP_CRY) {
4613         genModbits(left,right,result);
4614         goto release ;
4615     }
4616
4617     /* if both are of size == 1 */
4618     if (AOP_SIZE(left) == 1 &&
4619         AOP_SIZE(right) == 1 ) {
4620         genModOneByte(left,right,result);
4621         goto release ;
4622     }
4623
4624     /* should have been converted to function call */
4625     assert(0);
4626
4627 release :
4628     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4630     pic16_freeAsmop(result,NULL,ic,TRUE); 
4631 }
4632
4633 /*-----------------------------------------------------------------*/
4634 /* genIfxJump :- will create a jump depending on the ifx           */
4635 /*-----------------------------------------------------------------*/
4636 /*
4637   note: May need to add parameter to indicate when a variable is in bit space.
4638 */
4639 static void genIfxJump (iCode *ic, char *jval)
4640 {
4641   FENTRY;
4642   
4643     /* if true label then we jump if condition
4644     supplied is true */
4645     if ( IC_TRUE(ic) ) {
4646
4647         if(strcmp(jval,"a") == 0)
4648           emitSKPZ;
4649         else if (strcmp(jval,"c") == 0)
4650           emitSKPNC;
4651         else {
4652           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4653           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4654         }
4655
4656         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4657         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4658
4659     }
4660     else {
4661         /* false label is present */
4662         if(strcmp(jval,"a") == 0)
4663           emitSKPNZ;
4664         else if (strcmp(jval,"c") == 0)
4665           emitSKPC;
4666         else {
4667           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4668           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4669         }
4670
4671         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4672         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4673
4674     }
4675
4676
4677     /* mark the icode as generated */
4678     ic->generated = 1;
4679 }
4680
4681 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4682 {
4683   FENTRY;
4684   
4685     /* if true label then we jump if condition
4686     supplied is true */
4687     if ( IC_TRUE(ic) ) {
4688       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4689       pic16_emitpcode(POC_BTFSC, jop);
4690
4691       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4692       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4693
4694     } else {
4695       /* false label is present */
4696       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4697       pic16_emitpcode(POC_BTFSS, jop);
4698           
4699       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4700       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4701     }
4702
4703
4704     /* mark the icode as generated */
4705     ic->generated = 1;
4706 }
4707
4708 #if 0
4709 // not needed ATM
4710
4711 /*-----------------------------------------------------------------*/
4712 /* genSkip                                                         */
4713 /*-----------------------------------------------------------------*/
4714 static void genSkip(iCode *ifx,int status_bit)
4715 {
4716   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4717   if(!ifx)
4718     return;
4719
4720   if ( IC_TRUE(ifx) ) {
4721     switch(status_bit) {
4722     case 'z':
4723       emitSKPNZ;
4724       break;
4725
4726     case 'c':
4727       emitSKPNC;
4728       break;
4729
4730     case 'd':
4731       emitSKPDC;
4732       break;
4733
4734     }
4735
4736     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4737     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4738
4739   } else {
4740
4741     switch(status_bit) {
4742
4743     case 'z':
4744       emitSKPZ;
4745       break;
4746
4747     case 'c':
4748       emitSKPC;
4749       break;
4750
4751     case 'd':
4752       emitSKPDC;
4753       break;
4754     }
4755     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4756     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4757
4758   }
4759
4760 }
4761 #endif
4762
4763 /*-----------------------------------------------------------------*/
4764 /* genSkipc                                                        */
4765 /*-----------------------------------------------------------------*/
4766 static void genSkipc(resolvedIfx *rifx)
4767 {
4768   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4769   
4770   if(!rifx)
4771     return;
4772
4773   if(rifx->condition)
4774     emitSKPNC;
4775   else
4776     emitSKPC;
4777
4778   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4779   rifx->generated = 1;
4780 }
4781
4782 #if !(USE_SIMPLE_GENCMP)
4783 /*-----------------------------------------------------------------*/
4784 /* genSkipz2                                                       */
4785 /*-----------------------------------------------------------------*/
4786 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4787 {
4788   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4789   
4790   if(!rifx)
4791     return;
4792
4793   if( (rifx->condition ^ invert_condition) & 1)
4794     emitSKPZ;
4795   else
4796     emitSKPNZ;
4797
4798   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4799   rifx->generated = 1;
4800 }
4801 #endif
4802
4803 #if 0
4804 /*-----------------------------------------------------------------*/
4805 /* genSkipz                                                        */
4806 /*-----------------------------------------------------------------*/
4807 static void genSkipz(iCode *ifx, int condition)
4808 {
4809   if(!ifx)
4810     return;
4811
4812   if(condition)
4813     emitSKPNZ;
4814   else
4815     emitSKPZ;
4816
4817   if ( IC_TRUE(ifx) )
4818     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4819   else
4820     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4821
4822   if ( IC_TRUE(ifx) )
4823     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4824   else
4825     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4826
4827 }
4828 #endif
4829
4830 #if !(USE_SIMPLE_GENCMP)
4831 /*-----------------------------------------------------------------*/
4832 /* genSkipCond                                                     */
4833 /*-----------------------------------------------------------------*/
4834 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4835 {
4836   if(!rifx)
4837     return;
4838
4839   if(rifx->condition)
4840     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4841   else
4842     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4843
4844
4845   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4846   rifx->generated = 1;
4847 }
4848 #endif
4849
4850 #if 0
4851 /*-----------------------------------------------------------------*/
4852 /* genChkZeroes :- greater or less than comparison                 */
4853 /*     For each byte in a literal that is zero, inclusive or the   */
4854 /*     the corresponding byte in the operand with W                */
4855 /*     returns true if any of the bytes are zero                   */
4856 /*-----------------------------------------------------------------*/
4857 static int genChkZeroes(operand *op, int lit,  int size)
4858 {
4859
4860   int i;
4861   int flag =1;
4862
4863   while(size--) {
4864     i = (lit >> (size*8)) & 0xff;
4865
4866     if(i==0) {
4867       if(flag) 
4868         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4869       else
4870         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4871       flag = 0;
4872     }
4873   }
4874
4875   return (flag==0);
4876 }
4877 #endif
4878
4879
4880 /*-----------------------------------------------------------------*/
4881 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4882 /*                  aop (if it's NOT a literal) or from lit (if    */
4883 /*                  aop is a literal)                              */
4884 /*-----------------------------------------------------------------*/
4885 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4886   if (aop->type == AOP_LIT) {
4887     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4888   } else {
4889     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4890   }
4891 }
4892
4893 /*-----------------------------------------------------------------*/
4894 /* genCmp :- greater or less than comparison                       */
4895 /*-----------------------------------------------------------------*/
4896
4897 #if USE_SIMPLE_GENCMP           /* { */
4898
4899 /* genCmp performs a left < right comparison, stores
4900  * the outcome in result (if != NULL) and generates
4901  * control flow code for the ifx (if != NULL).
4902  *
4903  * This version leaves in sequences like
4904  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4905  * which should be optmized by the peephole
4906  * optimizer - RN 2005-01-01 */
4907 static void genCmp (operand *left,operand *right,
4908                     operand *result, iCode *ifx, int sign)
4909 {
4910   resolvedIfx rIfx;
4911   int size;
4912   int offs;
4913   symbol *templbl;
4914   operand *dummy;
4915   unsigned long lit;
4916   unsigned long mask;
4917   int performedLt;
4918
4919   FENTRY;
4920   
4921   assert (left && right);
4922   assert (AOP_SIZE(left) == AOP_SIZE(right));
4923
4924   size = AOP_SIZE(right) - 1;
4925   mask = (0x100UL << (size*8)) - 1;
4926   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4927   performedLt = 1;
4928   templbl = NULL;
4929   lit = 0;
4930   
4931   resolveIfx (&rIfx, ifx);
4932
4933   /* handle for special cases */
4934   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4935       return;
4936
4937   /**********************************************************************
4938    * handle bits - bit compares are promoted to int compares seemingly! *
4939    **********************************************************************/
4940 #if 0
4941   // THIS IS COMPLETELY UNTESTED!
4942   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4943     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4944     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4945     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4946
4947     emitSETC;
4948     // 1 < {0,1} is false --> clear C by skipping the next instruction
4949     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4950     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4951     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4952     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4953     emitCLRC; // only skipped for left=0 && right=1
4954
4955     goto correct_result_in_carry;
4956   } // if
4957 #endif
4958
4959   /*************************************************
4960    * make sure that left is register (or the like) *
4961    *************************************************/
4962   if (!isAOP_REGlike(left)) {
4963     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4964     assert (isAOP_LIT(left));
4965     assert (isAOP_REGlike(right));
4966     // swap left and right
4967     // left < right <==> right > left <==> (right >= left + 1)
4968     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4969
4970     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4971       // MAXVALUE < right? always false
4972       if (performedLt) emitCLRC; else emitSETC;
4973       goto correct_result_in_carry;
4974     } // if
4975
4976     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4977     // that's why we handled it above.
4978     lit++;
4979
4980     dummy = left;
4981     left = right;
4982     right = dummy;
4983
4984     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4985   } else if (isAOP_LIT(right)) {
4986     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4987   } // if
4988
4989   assert (isAOP_REGlike(left)); // left must be register or the like
4990   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4991
4992   /*************************************************
4993    * special cases go here                         *
4994    *************************************************/
4995
4996   if (isAOP_LIT(right)) {
4997     if (!sign) {
4998       // unsigned comparison to a literal
4999       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5000       if (lit == 0) {
5001         // unsigned left < 0? always false
5002         if (performedLt) emitCLRC; else emitSETC;
5003         goto correct_result_in_carry;
5004       }
5005     } else {
5006       // signed comparison to a literal
5007       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5008       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5009         // signed left < 0x80000000? always false
5010         if (performedLt) emitCLRC; else emitSETC;
5011         goto correct_result_in_carry;
5012       } else if (lit == 0) {
5013         // compare left < 0; set CARRY if SIGNBIT(left) is set
5014         if (performedLt) emitSETC; else emitCLRC;
5015         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5016         if (performedLt) emitCLRC; else emitSETC;
5017         goto correct_result_in_carry;
5018       }
5019     } // if (!sign)
5020   } // right is literal
5021
5022   /*************************************************
5023    * perform a general case comparison             *
5024    * make sure we get CARRY==1 <==> left >= right  *
5025    *************************************************/
5026   // compare most significant bytes
5027   //DEBUGpc ("comparing bytes at offset %d", size);
5028   if (!sign) {
5029     // unsigned comparison
5030     mov2w_regOrLit (AOP(right), lit, size);
5031     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5032   } else {
5033     // signed comparison
5034     // (add 2^n to both operands then perform an unsigned comparison)
5035     if (isAOP_LIT(right)) {
5036       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5037       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5038
5039       if (litbyte == 0x80) {
5040         // left >= 0x80 -- always true, but more bytes to come
5041         pic16_mov2w (AOP(left), size);
5042         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5043         emitSETC;
5044       } else {
5045         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5046         pic16_mov2w (AOP(left), size);
5047         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5048         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5049       } // if
5050     } else {
5051       /* using PRODL as a temporary register here */
5052       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5053       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5054       pic16_mov2w (AOP(left), size);
5055       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5056       pic16_emitpcode (POC_MOVWF, pctemp);
5057       pic16_mov2w (AOP(right), size);
5058       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5059       pic16_emitpcode (POC_SUBFW, pctemp);
5060       //pic16_popReleaseTempReg(pctemp, 1);
5061     }
5062   } // if (!sign)
5063
5064   // compare remaining bytes (treat as unsigned case from above)
5065   templbl = newiTempLabel ( NULL );
5066   offs = size;
5067   while (offs--) {
5068     //DEBUGpc ("comparing bytes at offset %d", offs);
5069     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5070     mov2w_regOrLit (AOP(right), lit, offs);
5071     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5072   } // while (offs)
5073   pic16_emitpLabel (templbl->key);
5074   goto result_in_carry;
5075
5076 result_in_carry:
5077   
5078   /****************************************************
5079    * now CARRY contains the result of the comparison: *
5080    * SUBWF sets CARRY iff                             *
5081    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5082    * (F=left, W=right)                                *
5083    ****************************************************/
5084
5085   if (performedLt) {
5086     if (result && AOP_TYPE(result) != AOP_CRY) {
5087       // value will be stored
5088       emitTOGC;
5089     } else {
5090       // value wil only be used in the following genSkipc()
5091       rIfx.condition ^= 1;
5092     }
5093   } // if
5094
5095 correct_result_in_carry:
5096
5097   // assign result to variable (if neccessary)
5098   if (result && AOP_TYPE(result) != AOP_CRY) {
5099     //DEBUGpc ("assign result");
5100     size = AOP_SIZE(result);
5101     while (size--) {
5102       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5103     } // while
5104     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5105   } // if (result)
5106
5107   // perform conditional jump
5108   if (ifx) {
5109     //DEBUGpc ("generate control flow");
5110     genSkipc (&rIfx);
5111     ifx->generated = 1;
5112   } // if
5113 }
5114
5115 #elif 1         /* } */
5116                 /* { */
5117       /* original code */
5118 static void genCmp (operand *left,operand *right,
5119                     operand *result, iCode *ifx, int sign)
5120 {
5121   int size; //, offset = 0 ;
5122   unsigned long lit = 0L,i = 0;
5123   resolvedIfx rFalseIfx;
5124   //  resolvedIfx rTrueIfx;
5125   symbol *truelbl;
5126   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5127 /*
5128   if(ifx) {
5129     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5130     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5131   }
5132 */
5133
5134   FENTRY;
5135   
5136   resolveIfx(&rFalseIfx,ifx);
5137   truelbl  = newiTempLabel(NULL);
5138   size = max(AOP_SIZE(left),AOP_SIZE(right));
5139
5140   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5141
5142 #define _swapp
5143
5144   /* if literal is on the right then swap with left */
5145   if ((AOP_TYPE(right) == AOP_LIT)) {
5146     operand *tmp = right ;
5147     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5148     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5149 #ifdef _swapp
5150
5151     lit = (lit - 1) & mask;
5152     right = left;
5153     left = tmp;
5154     rFalseIfx.condition ^= 1;
5155 #endif
5156
5157   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5158     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5159   }
5160
5161
5162   //if(IC_TRUE(ifx) == NULL)
5163   /* if left & right are bit variables */
5164   if (AOP_TYPE(left) == AOP_CRY &&
5165       AOP_TYPE(right) == AOP_CRY ) {
5166     assert (0 && "bit variables used in genCmp");
5167     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5168     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5169   } else {
5170     /* subtract right from left if at the
5171        end the carry flag is set then we know that
5172        left is greater than right */
5173
5174     symbol *lbl  = newiTempLabel(NULL);
5175
5176 #if 0
5177         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5178                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5179 #endif
5180
5181 #ifndef _swapp
5182     if(AOP_TYPE(right) == AOP_LIT) {
5183
5184       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5185
5186       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5187
5188       /* special cases */
5189
5190       if(lit == 0) {
5191
5192         if(sign != 0) 
5193           genSkipCond(&rFalseIfx,left,size-1,7);
5194         else 
5195           /* no need to compare to 0...*/
5196           /* NOTE: this is a de-generate compare that most certainly 
5197            *       creates some dead code. */
5198           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5199
5200         if(ifx) ifx->generated = 1;
5201         return;
5202
5203       }
5204       size--;
5205
5206       if(size == 0) {
5207         //i = (lit >> (size*8)) & 0xff;
5208         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5209         
5210         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5211
5212         i = ((0-lit) & 0xff);
5213         if(sign) {
5214           if( i == 0x81) { 
5215             /* lit is 0x7f, all signed chars are less than
5216              * this except for 0x7f itself */
5217             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5218             genSkipz2(&rFalseIfx,0);
5219           } else {
5220             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5221             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5222             genSkipc(&rFalseIfx);
5223           }
5224
5225         } else {
5226           if(lit == 1) {
5227             genSkipz2(&rFalseIfx,1);
5228           } else {
5229             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5230             genSkipc(&rFalseIfx);
5231           }
5232         }
5233
5234         if(ifx) ifx->generated = 1;
5235         return;
5236       }
5237
5238       /* chars are out of the way. now do ints and longs */
5239
5240
5241       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5242         
5243       /* special cases */
5244
5245       if(sign) {
5246
5247         if(lit == 0) {
5248           genSkipCond(&rFalseIfx,left,size,7);
5249           if(ifx) ifx->generated = 1;
5250           return;
5251         }
5252
5253         if(lit <0x100) {
5254           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5255
5256           //rFalseIfx.condition ^= 1;
5257           //genSkipCond(&rFalseIfx,left,size,7);
5258           //rFalseIfx.condition ^= 1;
5259
5260           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5261           if(rFalseIfx.condition)
5262             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5263           else
5264             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5265
5266           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5267           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5268           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5269
5270           while(size > 1)
5271             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5272
5273           if(rFalseIfx.condition) {
5274             emitSKPZ;
5275             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5276
5277           } else {
5278             emitSKPNZ;
5279           }
5280
5281           genSkipc(&rFalseIfx);
5282           pic16_emitpLabel(truelbl->key);
5283           if(ifx) ifx->generated = 1;
5284           return;
5285
5286         }
5287
5288         if(size == 1) {
5289
5290           if( (lit & 0xff) == 0) {
5291             /* lower byte is zero */
5292             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5293             i = ((lit >> 8) & 0xff) ^0x80;
5294             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5295             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5297             genSkipc(&rFalseIfx);
5298
5299
5300             if(ifx) ifx->generated = 1;
5301             return;
5302
5303           }
5304         } else {
5305           /* Special cases for signed longs */
5306           if( (lit & 0xffffff) == 0) {
5307             /* lower byte is zero */
5308             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5309             i = ((lit >> 8*3) & 0xff) ^0x80;
5310             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5311             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5312             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5313             genSkipc(&rFalseIfx);
5314
5315
5316             if(ifx) ifx->generated = 1;
5317             return;
5318
5319           }
5320
5321         }
5322
5323
5324         if(lit & (0x80 << (size*8))) {
5325           /* lit is negative */
5326           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5327
5328           //genSkipCond(&rFalseIfx,left,size,7);
5329
5330           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5331
5332           if(rFalseIfx.condition)
5333             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5334           else
5335             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5336
5337
5338         } else {
5339           /* lit is positive */
5340           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5341           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5342           if(rFalseIfx.condition)
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5344           else
5345             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5346
5347         }
5348
5349         /*
5350           This works, but is only good for ints.
5351           It also requires a "known zero" register.
5352           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5353           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5354           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5355           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5356           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5357           genSkipc(&rFalseIfx);
5358
5359           pic16_emitpLabel(truelbl->key);
5360           if(ifx) ifx->generated = 1;
5361           return;
5362         **/
5363           
5364         /* There are no more special cases, so perform a general compare */
5365   
5366         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5367         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5368
5369         while(size--) {
5370
5371           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5372           emitSKPNZ;
5373           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5374         }
5375         //rFalseIfx.condition ^= 1;
5376         genSkipc(&rFalseIfx);
5377
5378         pic16_emitpLabel(truelbl->key);
5379
5380         if(ifx) ifx->generated = 1;
5381         return;
5382
5383
5384       }
5385
5386
5387       /* sign is out of the way. So now do an unsigned compare */
5388       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5389
5390
5391       /* General case - compare to an unsigned literal on the right.*/
5392
5393       i = (lit >> (size*8)) & 0xff;
5394       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5395       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5396       while(size--) {
5397         i = (lit >> (size*8)) & 0xff;
5398
5399         if(i) {
5400           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5401           emitSKPNZ;
5402           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5403         } else {
5404           /* this byte of the lit is zero, 
5405            *if it's not the last then OR in the variable */
5406           if(size)
5407             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5408         }
5409       }
5410
5411
5412       pic16_emitpLabel(lbl->key);
5413 //      pic16_emitpLabel(truelbl->key);
5414       //if(emitFinalCheck)
5415       genSkipc(&rFalseIfx);
5416       if(sign)
5417         pic16_emitpLabel(truelbl->key);
5418
5419       if(ifx) ifx->generated = 1;
5420       return;
5421
5422
5423     }
5424 #endif  // _swapp
5425
5426     if(AOP_TYPE(left) == AOP_LIT) {
5427       //symbol *lbl = newiTempLabel(NULL);
5428
5429       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5430
5431
5432       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5433
5434       /* Special cases */
5435       if((lit == 0) && (sign == 0)){
5436
5437         size--;
5438         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5439         while(size) 
5440           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5441
5442         genSkipz2(&rFalseIfx,0);
5443         if(ifx) ifx->generated = 1;
5444         return;
5445       }
5446
5447       if(size==1) {
5448         /* Special cases */
5449         lit &= 0xff;
5450         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5451           /* degenerate compare can never be true */
5452           if(rFalseIfx.condition == 0)
5453             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5454
5455           if(ifx) ifx->generated = 1;
5456           return;
5457         }
5458
5459         if(sign) {
5460           /* signed comparisons to a literal byte */
5461
5462           int lp1 = (lit+1) & 0xff;
5463
5464           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5465           switch (lp1) {
5466           case 0:
5467             rFalseIfx.condition ^= 1;
5468             genSkipCond(&rFalseIfx,right,0,7);
5469             break;
5470           case 0x7f:
5471             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5472             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5473             genSkipz2(&rFalseIfx,1);
5474             break;
5475           default:
5476             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5477             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5478             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5479             rFalseIfx.condition ^= 1;
5480             genSkipc(&rFalseIfx);
5481             break;
5482           }
5483         } else {
5484           /* unsigned comparisons to a literal byte */
5485
5486           switch(lit & 0xff ) {
5487           case 0:
5488             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5489             genSkipz2(&rFalseIfx,0);
5490             break;
5491           case 0x7f:
5492             rFalseIfx.condition ^= 1;
5493             genSkipCond(&rFalseIfx,right,0,7);
5494             break;
5495
5496           default:
5497             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5498             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5499             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5500             rFalseIfx.condition ^= 1;
5501             if (AOP_TYPE(result) == AOP_CRY)
5502               genSkipc(&rFalseIfx);
5503             else {
5504               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5505               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5506             }         
5507             break;
5508           }
5509         }
5510
5511         if(ifx) ifx->generated = 1;
5512         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5513                 goto check_carry;
5514         return;
5515
5516       } else {
5517
5518         /* Size is greater than 1 */
5519
5520         if(sign) {
5521           int lp1 = lit+1;
5522
5523           size--;
5524
5525           if(lp1 == 0) {
5526             /* this means lit = 0xffffffff, or -1 */
5527
5528
5529             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5530             rFalseIfx.condition ^= 1;
5531             genSkipCond(&rFalseIfx,right,size,7);
5532             if(ifx) ifx->generated = 1;
5533
5534             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5535               goto check_carry;
5536
5537             return;
5538           }
5539
5540           if(lit == 0) {
5541             int s = size;
5542
5543             if(rFalseIfx.condition) {
5544               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5545               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5546             }
5547
5548             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5549             while(size--)
5550               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5551
5552
5553             emitSKPZ;
5554             if(rFalseIfx.condition) {
5555               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5556               pic16_emitpLabel(truelbl->key);
5557             }else {
5558               rFalseIfx.condition ^= 1;
5559               genSkipCond(&rFalseIfx,right,s,7);
5560             }
5561
5562             if(ifx) ifx->generated = 1;
5563
5564             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5565               goto check_carry;
5566
5567             return;
5568           }
5569
5570           if((size == 1) &&  (0 == (lp1&0xff))) {
5571             /* lower byte of signed word is zero */
5572             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5573             i = ((lp1 >> 8) & 0xff) ^0x80;
5574             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5575             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5576             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5577
5578             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5579               emitTOGC;
5580               if(ifx) ifx->generated = 1;
5581               goto check_carry;
5582             } else {
5583               rFalseIfx.condition ^= 1;
5584               genSkipc(&rFalseIfx);
5585               if(ifx) ifx->generated = 1;
5586             }
5587
5588             return;
5589           }
5590
5591           if(lit & (0x80 << (size*8))) {
5592             /* Lit is less than zero */
5593             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5594             //rFalseIfx.condition ^= 1;
5595             //genSkipCond(&rFalseIfx,left,size,7);
5596             //rFalseIfx.condition ^= 1;
5597             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5598             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5599
5600             if(rFalseIfx.condition)
5601               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5602             else
5603               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5604
5605
5606           } else {
5607             /* Lit is greater than or equal to zero */
5608             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5609             //rFalseIfx.condition ^= 1;
5610             //genSkipCond(&rFalseIfx,right,size,7);
5611             //rFalseIfx.condition ^= 1;
5612
5613             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5614             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5615
5616             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5617             if(rFalseIfx.condition)
5618               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5619             else
5620               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5621
5622           }
5623
5624           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5625           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5626
5627           while(size--) {
5628
5629             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5630             emitSKPNZ;
5631             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5632           }
5633           rFalseIfx.condition ^= 1;
5634           //rFalseIfx.condition = 1;
5635           genSkipc(&rFalseIfx);
5636
5637           pic16_emitpLabel(truelbl->key);
5638
5639           if(ifx) ifx->generated = 1;
5640
5641
5642           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5643             goto check_carry;
5644
5645           return;
5646           // end of if (sign)
5647         } else {
5648
5649           /* compare word or long to an unsigned literal on the right.*/
5650
5651
5652           size--;
5653           if(lit < 0xff) {
5654             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5655             switch (lit) {
5656             case 0:
5657               break; /* handled above */
5658 /*
5659             case 0xff:
5660               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5661               while(size--)
5662                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5663               genSkipz2(&rFalseIfx,0);
5664               break;
5665 */
5666             default:
5667               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5668               while(--size)
5669                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5670
5671               emitSKPZ;
5672               if(rFalseIfx.condition)
5673                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5674               else
5675                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5676
5677
5678               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5679               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5680
5681               rFalseIfx.condition ^= 1;
5682               genSkipc(&rFalseIfx);
5683             }
5684
5685             pic16_emitpLabel(truelbl->key);
5686
5687             if(ifx) ifx->generated = 1;
5688
5689             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5690               goto check_carry;
5691
5692             return;
5693           }
5694
5695
5696           lit++;
5697           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5698           i = (lit >> (size*8)) & 0xff;
5699
5700           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5701           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5702
5703           while(size--) {
5704             i = (lit >> (size*8)) & 0xff;
5705
5706             if(i) {
5707               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5708               emitSKPNZ;
5709               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5710             } else {
5711               /* this byte of the lit is zero, 
5712                * if it's not the last then OR in the variable */
5713               if(size)
5714                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5715             }
5716           }
5717
5718
5719           pic16_emitpLabel(lbl->key);
5720
5721           rFalseIfx.condition ^= 1;
5722
5723           genSkipc(&rFalseIfx);
5724         }
5725
5726         if(sign)
5727           pic16_emitpLabel(truelbl->key);
5728         if(ifx) ifx->generated = 1;
5729
5730             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5731               goto check_carry;
5732
5733         return;
5734       }
5735     }
5736     /* Compare two variables */
5737
5738     DEBUGpic16_emitcode(";sign","%d",sign);
5739
5740     size--;
5741     if(sign) {
5742       /* Sigh. thus sucks... */
5743       if(size) {
5744         pCodeOp *pctemp;
5745         
5746         pctemp = pic16_popGetTempReg(1);
5747         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5748         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5749         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5750         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5751         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5752         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5753         pic16_popReleaseTempReg(pctemp, 1);
5754       } else {
5755         /* Signed char comparison */
5756         /* Special thanks to Nikolai Golovchenko for this snippet */
5757         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5758         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5759         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5760         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5761         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5762         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5763
5764         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5765         genSkipc(&rFalseIfx);
5766           
5767         if(ifx) ifx->generated = 1;
5768
5769             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5770               goto check_carry;
5771
5772         return;
5773       }
5774
5775     } else {
5776
5777       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5778       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5779     }
5780
5781
5782     /* The rest of the bytes of a multi-byte compare */
5783     while (size) {
5784
5785       emitSKPZ;
5786       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5787       size--;
5788
5789       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5790       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5791
5792
5793     }
5794
5795     pic16_emitpLabel(lbl->key);
5796
5797     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5798     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5799         (AOP_TYPE(result) == AOP_REG)) {
5800       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5801       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5802     } else {
5803       genSkipc(&rFalseIfx);
5804     }         
5805     //genSkipc(&rFalseIfx);
5806     if(ifx) ifx->generated = 1;
5807
5808
5809             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5810               goto check_carry;
5811
5812     return;
5813
5814   }
5815
5816 check_carry:
5817   if ((AOP_TYPE(result) != AOP_CRY) 
5818         && AOP_SIZE(result)) {
5819     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5820
5821     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5822
5823     pic16_outBitC(result);
5824   } else {
5825     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5826     /* if the result is used in the next
5827        ifx conditional branch then generate
5828        code a little differently */
5829     if (ifx )
5830       genIfxJump (ifx,"c");
5831     else
5832       pic16_outBitC(result);
5833     /* leave the result in acc */
5834   }
5835
5836 }
5837
5838 #elif 0 /* VR version of genCmp() */    /* } else { */
5839
5840 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5841 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5842         operand *result, int offset, int invert_op)
5843 {
5844   /* add code here */
5845   
5846   /* check condition, > or < ?? */
5847   if(rIfx->condition != 0)invert_op ^= 1;
5848   
5849   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5850
5851   if(!ifx)invert_op ^= 1;
5852
5853   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5854       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5855   
5856   /* do selection */
5857   if(!invert_op)return POC_CPFSGT;
5858   else return POC_CPFSLT;
5859 }
5860
5861 static int compareAopfirstpass=1;
5862
5863 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5864             operand *oper, int offset, operand *result,
5865             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5866             symbol *tlbl)
5867 {
5868   int op;
5869   symbol *truelbl;
5870
5871   /* invert if there is a result to be loaded, in order to fit,
5872    * SETC/CLRC sequence */
5873   if(AOP_SIZE(result))invert_op ^= 1;
5874
5875 //  if(sign && !offset)invert_op ^= 1;
5876   
5877 //  if(sign)invert_op ^= 1;
5878   
5879   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5880
5881   if(AOP_SIZE(result) && compareAopfirstpass) {
5882     if(!ifx) {
5883       if(pcop2)
5884         pic16_emitpcode(POC_SETF, pcop2);
5885       else
5886         emitSETC;
5887     } else {
5888       if(pcop2)
5889         pic16_emitpcode(POC_CLRF, pcop2);
5890       else
5891         emitCLRC;
5892     }
5893   }
5894
5895   compareAopfirstpass = 0;
5896
5897       /* there is a bug when comparing operands with size > 1,
5898        * because higher bytes can be equal and test should be performed
5899        * to the next lower byte, current algorithm, considers operands
5900        * inequal in these cases! -- VR 20041107 */
5901
5902     
5903   if(pcop)
5904     pic16_emitpcode(op, pcop);
5905   else
5906     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5907
5908
5909   if((!sign || !offset) && AOP_SIZE(result)) {
5910     if(!ifx) {
5911       if(pcop2)
5912         pic16_emitpcode(POC_CLRF, pcop2);
5913         else
5914         emitCLRC;
5915     } else {
5916       if(pcop2)
5917         pic16_emitpcode(POC_SETF, pcop2);
5918       else
5919         emitSETC;
5920     }
5921     
5922     /* don't emit final branch (offset == 0) */
5923     if(offset) {
5924
5925       if(pcop2)
5926         pic16_emitpcode(POC_RRCF, pcop2);
5927
5928       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5929     }
5930   } else {
5931     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5932       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5933             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5934
5935       truelbl = newiTempLabel( NULL );
5936       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5937       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5938         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5939       else
5940         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5941       pic16_emitpLabel(truelbl->key);
5942     } else {
5943       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5944     }
5945   }
5946 }
5947
5948 static void genCmp (operand *left, operand *right,
5949                     operand *result, iCode *ifx, int sign)
5950 {
5951   int size, cmpop=1;
5952   long lit = 0L;
5953   resolvedIfx rFalseIfx;
5954   symbol *falselbl, *tlbl;
5955
5956     FENTRY;
5957     
5958     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5959
5960     resolveIfx(&rFalseIfx, ifx);
5961     size = max(AOP_SIZE(left), AOP_SIZE(right));
5962     
5963     /* if left & right are bit variables */
5964     if(AOP_TYPE(left) == AOP_CRY
5965       && AOP_TYPE(right) == AOP_CRY ) {
5966
5967         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5968         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5969         
5970         werror(W_POSSBUG2, __FILE__, __LINE__);
5971         exit(-1);
5972     }
5973     
5974     /* if literal is on the right then swap with left */
5975     if((AOP_TYPE(right) == AOP_LIT)) {
5976       operand *tmp = right ;
5977 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5978
5979         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5980
5981 //      lit = (lit - 1) & mask;
5982         right = left;
5983         left = tmp;
5984         rFalseIfx.condition ^= 1;               /* reverse compare */
5985     } else
5986     if ((AOP_TYPE(left) == AOP_LIT)) {
5987       /* float compares are handled by support functions */
5988       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5989     }
5990
5991     /* actual comparing algorithm */
5992 //    size = AOP_SIZE( right );
5993
5994     falselbl = newiTempLabel( NULL );
5995     if(AOP_TYPE(left) == AOP_LIT) {
5996       /* compare to literal */
5997       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5998       
5999       if(sign) {
6000         pCodeOp *pct, *pct2;
6001         symbol *tlbl1;
6002
6003         /* signed compare */
6004         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6005
6006         /* using PRODL:PRODH as a temporary register here */
6007         pct = pic16_popCopyReg(&pic16_pc_prodl);
6008         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6009         tlbl = newiTempLabel( NULL );
6010         
6011         /* first compare signs:
6012          *  a. if both are positive, compare just like unsigned
6013          *  b. if both are negative, invert cmpop, compare just like unsigned
6014          *  c. if different signs, determine the result directly */
6015
6016         size--;
6017
6018 #if 1
6019         /* { */
6020         tlbl1 = newiTempLabel( NULL );
6021 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6022
6023         if(lit > 0) {
6024
6025           /* literal is zero or positive:
6026            *  a. if carry is zero, too, continue compare,
6027            *  b. if carry is set, then continue depending on cmpop ^ condition:
6028            *    1. '<' return false (literal < variable),
6029            *    2. '>' return true (literal > variable) */
6030 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6031           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6032           
6033           
6034           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6035           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6036         } else 
6037         if(lit < 0) {
6038           
6039           /* literal is negative:
6040            *  a. if carry is set, too, continue compare,
6041            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6042            *    1. '<' return true (literal < variable),
6043            *    2. '>' return false (literal > variable) */
6044 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6045           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6046           
6047           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6048           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6049         }
6050 #if 1
6051         else {
6052           /* lit == 0 */
6053           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6054           
6055           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6056           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6057         }
6058 #endif
6059         
6060         
6061         pic16_emitpLabel( tlbl1->key );
6062 #endif  /* } */
6063
6064         compareAopfirstpass=1;
6065 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6066 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6067 //        pic16_emitpcode(POC_MOVWF, pct);
6068
6069 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6070         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6071 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6072         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6073
6074         /* generic case */        
6075           while( size-- ) {
6076 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6077 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6078 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6079 //            pic16_emitpcode(POC_MOVWF, pct);
6080
6081 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6082             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6083             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6084 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6085 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6086           }
6087         
6088         if(ifx)ifx->generated = 1;
6089
6090         if(AOP_SIZE(result)) {
6091           pic16_emitpLabel(tlbl->key);
6092           pic16_emitpLabel(falselbl->key);
6093           pic16_outBitOp( result, pct2 );
6094         } else {
6095           pic16_emitpLabel(tlbl->key);
6096         }
6097       } else {
6098
6099         /* unsigned compare */      
6100         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6101     
6102         compareAopfirstpass=1;
6103         while(size--) {
6104           
6105           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6106           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6107
6108         }
6109         if(ifx)ifx->generated = 1;
6110
6111         if(AOP_SIZE(result)) {
6112           pic16_emitpLabel(falselbl->key);
6113           pic16_outBitC( result );
6114         }
6115
6116       }
6117     } else {
6118       /* compare registers */
6119       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6120
6121
6122       if(sign) {
6123         pCodeOp *pct, *pct2;
6124         
6125         /* signed compare */
6126         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6127
6128         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6129         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6130         tlbl = newiTempLabel( NULL );
6131         
6132         compareAopfirstpass=1;
6133
6134         size--;
6135         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6136 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6137         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6138         pic16_emitpcode(POC_MOVWF, pct);
6139
6140         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6141 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6142         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6143
6144         /* WREG already holds left + 0x80 */
6145         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6146         
6147         while( size-- ) {
6148           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6149 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6150           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6151           pic16_emitpcode(POC_MOVWF, pct);
6152                 
6153           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6154 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6155           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6156
6157           /* WREG already holds left + 0x80 */
6158           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6159 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6160         }
6161         
6162         if(ifx)ifx->generated = 1;
6163
6164         if(AOP_SIZE(result)) {
6165           pic16_emitpLabel(tlbl->key);
6166           pic16_emitpLabel(falselbl->key);
6167           pic16_outBitOp( result, pct2 );
6168         } else {
6169           pic16_emitpLabel(tlbl->key);
6170         }
6171
6172       } else {
6173         /* unsigned compare */      
6174         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6175
6176         compareAopfirstpass=1;
6177         while(size--) {
6178           
6179           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6180           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6181
6182         }
6183
6184         if(ifx)ifx->generated = 1;
6185         if(AOP_SIZE(result)) {
6186
6187           pic16_emitpLabel(falselbl->key);
6188           pic16_outBitC( result );
6189         }
6190
6191       }
6192     }
6193 }
6194
6195 #endif  /* } */
6196
6197
6198
6199 /*-----------------------------------------------------------------*/
6200 /* genCmpGt :- greater than comparison                             */
6201 /*-----------------------------------------------------------------*/
6202 static void genCmpGt (iCode *ic, iCode *ifx)
6203 {
6204   operand *left, *right, *result;
6205   sym_link *letype , *retype;
6206   int sign ;
6207
6208     FENTRY;
6209     
6210     left = IC_LEFT(ic);
6211     right= IC_RIGHT(ic);
6212     result = IC_RESULT(ic);
6213
6214     letype = getSpec(operandType(left));
6215     retype =getSpec(operandType(right));
6216     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6217     /* assign the amsops */
6218     pic16_aopOp (left,ic,FALSE);
6219     pic16_aopOp (right,ic,FALSE);
6220     pic16_aopOp (result,ic,TRUE);
6221
6222     genCmp(right, left, result, ifx, sign);
6223
6224     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6225     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6226     pic16_freeAsmop(result,NULL,ic,TRUE); 
6227 }
6228
6229 /*-----------------------------------------------------------------*/
6230 /* genCmpLt - less than comparisons                                */
6231 /*-----------------------------------------------------------------*/
6232 static void genCmpLt (iCode *ic, iCode *ifx)
6233 {
6234   operand *left, *right, *result;
6235   sym_link *letype , *retype;
6236   int sign ;
6237
6238     FENTRY;
6239
6240     left = IC_LEFT(ic);
6241     right= IC_RIGHT(ic);
6242     result = IC_RESULT(ic);
6243
6244     letype = getSpec(operandType(left));
6245     retype =getSpec(operandType(right));
6246     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6247
6248     /* assign the amsops */
6249     pic16_aopOp (left,ic,FALSE);
6250     pic16_aopOp (right,ic,FALSE);
6251     pic16_aopOp (result,ic,TRUE);
6252
6253     genCmp(left, right, result, ifx, sign);
6254
6255     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6256     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6257     pic16_freeAsmop(result,NULL,ic,TRUE); 
6258 }
6259
6260 #if 0
6261 // not needed ATM
6262 // FIXME reenable literal optimisation when the pic16 port is stable
6263
6264 /*-----------------------------------------------------------------*/
6265 /* genc16bit2lit - compare a 16 bit value to a literal             */
6266 /*-----------------------------------------------------------------*/
6267 static void genc16bit2lit(operand *op, int lit, int offset)
6268 {
6269   int i;
6270
6271   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6272   if( (lit&0xff) == 0) 
6273     i=1;
6274   else
6275     i=0;
6276
6277   switch( BYTEofLONG(lit,i)) { 
6278   case 0:
6279     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6280     break;
6281   case 1:
6282     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6283     break;
6284   case 0xff:
6285     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6286     break;
6287   default:
6288     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6289     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6290   }
6291
6292   i ^= 1;
6293
6294   switch( BYTEofLONG(lit,i)) { 
6295   case 0:
6296     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6297     break;
6298   case 1:
6299     emitSKPNZ;
6300     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6301     break;
6302   case 0xff:
6303     emitSKPNZ;
6304     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6305     break;
6306   default:
6307     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6308     emitSKPNZ;
6309     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6310
6311   }
6312
6313 }
6314 #endif
6315
6316 #if 0
6317 // not needed ATM
6318 /*-----------------------------------------------------------------*/
6319 /* gencjneshort - compare and jump if not equal                    */
6320 /*-----------------------------------------------------------------*/
6321 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6322 {
6323   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6324   int offset = 0;
6325   int res_offset = 0;  /* the result may be a different size then left or right */
6326   int res_size = AOP_SIZE(result);
6327   resolvedIfx rIfx;
6328   symbol *lbl, *lbl_done;
6329
6330   unsigned long lit = 0L;
6331   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6332
6333   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6334   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6335   if(result)
6336     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6337   resolveIfx(&rIfx,ifx);
6338   lbl =  newiTempLabel(NULL);
6339   lbl_done =  newiTempLabel(NULL);
6340
6341
6342   /* if the left side is a literal or 
6343      if the right is in a pointer register and left 
6344      is not */
6345   if ((AOP_TYPE(left) == AOP_LIT) || 
6346       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6347     operand *t = right;
6348     right = left;
6349     left = t;
6350   }
6351   if(AOP_TYPE(right) == AOP_LIT)
6352     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6353
6354   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6355     preserve_result = 1;
6356
6357   if(result && !preserve_result)
6358     {
6359       int i;
6360       for(i = 0; i < AOP_SIZE(result); i++)
6361         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6362     }
6363
6364
6365   /* if the right side is a literal then anything goes */
6366   if (AOP_TYPE(right) == AOP_LIT &&
6367       AOP_TYPE(left) != AOP_DIR ) {
6368     switch(size) {
6369     case 2:
6370       genc16bit2lit(left, lit, 0);
6371       emitSKPZ;
6372       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6373       break;
6374     default:
6375       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6376       while (size--) {
6377         if(lit & 0xff) {
6378           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6379           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6380         } else {
6381           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6382         }
6383
6384         emitSKPZ;
6385         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6386         offset++;
6387         if(res_offset < res_size-1)
6388           res_offset++;
6389         lit >>= 8;
6390       }
6391       break;
6392     }
6393   }
6394
6395   /* if the right side is in a register or in direct space or
6396      if the left is a pointer register & right is not */    
6397   else if (AOP_TYPE(right) == AOP_REG ||
6398            AOP_TYPE(right) == AOP_DIR || 
6399            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6400            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6401     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6402     int lbl_key = lbl->key;
6403
6404     if(result) {
6405       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6406       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6407     }else {
6408       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6409       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6410               __FUNCTION__,__LINE__);
6411       return;
6412     }
6413    
6414 /*     switch(size) { */
6415 /*     case 2: */
6416 /*       genc16bit2lit(left, lit, 0); */
6417 /*       emitSKPNZ; */
6418 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6419 /*       break; */
6420 /*     default: */
6421     while (size--) {
6422       int emit_skip=1;
6423       if((AOP_TYPE(left) == AOP_DIR) && 
6424          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6425
6426         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6427         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6428
6429       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6430             
6431         switch (lit & 0xff) {
6432         case 0:
6433           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6434           break;
6435         case 1:
6436           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6437           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6438           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6439           emit_skip=0;
6440           break;
6441         case 0xff:
6442           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6443           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6444           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6445           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6446           emit_skip=0;
6447           break;
6448         default:
6449           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6450           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6451         }
6452         lit >>= 8;
6453
6454       } else {
6455         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6456       }
6457       if(emit_skip) {
6458         if(AOP_TYPE(result) == AOP_CRY) {
6459           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6460           if(rIfx.condition)
6461             emitSKPNZ;
6462           else
6463             emitSKPZ;
6464           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6465         } else {
6466           /* fix me. probably need to check result size too */
6467           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6468           if(rIfx.condition)
6469             emitSKPZ;
6470           else
6471             emitSKPNZ;
6472           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6473           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6474         }
6475         if(ifx)
6476           ifx->generated=1;
6477       }
6478       emit_skip++;
6479       offset++;
6480       if(res_offset < res_size-1)
6481         res_offset++;
6482     }
6483 /*       break; */
6484 /*     } */
6485   } else if(AOP_TYPE(right) == AOP_REG &&
6486             AOP_TYPE(left) != AOP_DIR){
6487
6488     while(size--) {
6489       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6490       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6491       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6492       if(rIfx.condition)
6493         emitSKPNZ;
6494       else
6495         emitSKPZ;
6496       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6497       offset++;
6498       if(res_offset < res_size-1)
6499         res_offset++;
6500     }
6501       
6502   }else{
6503     /* right is a pointer reg need both a & b */
6504     while(size--) {
6505       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6506       if(strcmp(l,"b"))
6507         pic16_emitcode("mov","b,%s",l);
6508       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6509       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6510       offset++;
6511     }
6512   }
6513
6514   if(result && preserve_result)
6515     {
6516       int i;
6517       for(i = 0; i < AOP_SIZE(result); i++)
6518         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6519     }
6520
6521   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6522
6523   if(result && preserve_result)
6524     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6525
6526   if(!rIfx.condition)
6527     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6528
6529   pic16_emitpLabel(lbl->key);
6530
6531   if(result && preserve_result)
6532     {
6533       int i;
6534       for(i = 0; i < AOP_SIZE(result); i++)
6535         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6536
6537       pic16_emitpLabel(lbl_done->key);
6538    }
6539
6540   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6541
6542   if(ifx)
6543     ifx->generated = 1;
6544 }
6545 #endif
6546
6547 #if 0
6548 /*-----------------------------------------------------------------*/
6549 /* gencjne - compare and jump if not equal                         */
6550 /*-----------------------------------------------------------------*/
6551 static void gencjne(operand *left, operand *right, iCode *ifx)
6552 {
6553     symbol *tlbl  = newiTempLabel(NULL);
6554
6555     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6556     gencjneshort(left, right, lbl);
6557
6558     pic16_emitcode("mov","a,%s",one);
6559     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6560     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6561     pic16_emitcode("clr","a");
6562     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6563
6564     pic16_emitpLabel(lbl->key);
6565     pic16_emitpLabel(tlbl->key);
6566
6567 }
6568 #endif
6569
6570
6571 /*-----------------------------------------------------------------*/
6572 /* is_LitOp - check if operand has to be treated as literal        */
6573 /*-----------------------------------------------------------------*/
6574 static bool is_LitOp(operand *op)
6575 {
6576   return ((AOP_TYPE(op) == AOP_LIT)
6577       || ( (AOP_TYPE(op) == AOP_PCODE)
6578           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6579               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6580 }
6581
6582 /*-----------------------------------------------------------------*/
6583 /* is_LitAOp - check if operand has to be treated as literal        */
6584 /*-----------------------------------------------------------------*/
6585 static bool is_LitAOp(asmop *aop)
6586 {
6587   return ((aop->type == AOP_LIT)
6588       || ( (aop->type == AOP_PCODE)
6589           && ( (aop->aopu.pcop->type == PO_LITERAL)
6590               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6591 }
6592
6593
6594
6595 /*-----------------------------------------------------------------*/
6596 /* genCmpEq - generates code for equal to                          */
6597 /*-----------------------------------------------------------------*/
6598 static void genCmpEq (iCode *ic, iCode *ifx)
6599 {
6600   operand *left, *right, *result;
6601   symbol *falselbl = newiTempLabel(NULL);
6602   symbol *donelbl = newiTempLabel(NULL);
6603
6604   int preserve_result = 0;
6605   int generate_result = 0;
6606   int i=0;
6607   unsigned long lit = -1;
6608
6609   FENTRY;
6610   
6611   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6612   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6613   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6614  
6615   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6616
6617   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6618     {
6619       werror(W_POSSBUG2, __FILE__, __LINE__);
6620       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6621       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6622       goto release;
6623     }
6624
6625   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6626     {
6627       operand *tmp = right ;
6628       right = left;
6629       left = tmp;
6630     }
6631
6632   if (AOP_TYPE(right) == AOP_LIT) {
6633     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6634   }
6635
6636   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6637     preserve_result = 1;
6638
6639   if(result && AOP_SIZE(result))
6640     generate_result = 1;
6641
6642   if(generate_result && !preserve_result)
6643     {
6644       for(i = 0; i < AOP_SIZE(result); i++)
6645         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6646     }
6647
6648   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6649   for(i=0; i < AOP_SIZE(left); i++)
6650     {
6651       if(AOP_TYPE(left) != AOP_ACC)
6652         {
6653           if(is_LitOp(left))
6654             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6655           else
6656             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6657         }
6658       if(is_LitOp(right)) {
6659         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6660           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6661         }
6662       } else
6663         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6664
6665       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6666     }
6667
6668   // result == true
6669
6670   if(generate_result && preserve_result)
6671     {
6672       for(i = 0; i < AOP_SIZE(result); i++)
6673         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6674     }
6675
6676   if(generate_result)
6677     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6678
6679   if(generate_result && preserve_result)
6680     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6681
6682   if(ifx && IC_TRUE(ifx))
6683     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6684
6685   if(ifx && IC_FALSE(ifx))
6686     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6687
6688   pic16_emitpLabel(falselbl->key);
6689
6690   // result == false
6691
6692   if(ifx && IC_FALSE(ifx))
6693     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6694
6695   if(generate_result && preserve_result)
6696     {
6697       for(i = 0; i < AOP_SIZE(result); i++)
6698         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6699     }
6700
6701   pic16_emitpLabel(donelbl->key);
6702
6703   if(ifx)
6704     ifx->generated = 1;
6705
6706 release:
6707   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6708   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6709   pic16_freeAsmop(result,NULL,ic,TRUE);
6710
6711 }
6712
6713
6714 #if 0
6715 // old version kept for reference
6716
6717 /*-----------------------------------------------------------------*/
6718 /* genCmpEq - generates code for equal to                          */
6719 /*-----------------------------------------------------------------*/
6720 static void genCmpEq (iCode *ic, iCode *ifx)
6721 {
6722     operand *left, *right, *result;
6723     unsigned long lit = 0L;
6724     int size,offset=0;
6725     symbol *falselbl  = newiTempLabel(NULL);
6726
6727
6728     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6729
6730     if(ifx)
6731       DEBUGpic16_emitcode ("; ifx is non-null","");
6732     else
6733       DEBUGpic16_emitcode ("; ifx is null","");
6734
6735     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6736     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6737     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6738
6739     size = max(AOP_SIZE(left),AOP_SIZE(right));
6740
6741     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6742
6743     /* if literal, literal on the right or 
6744     if the right is in a pointer register and left 
6745     is not */
6746     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6747         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6748       operand *tmp = right ;
6749       right = left;
6750       left = tmp;
6751     }
6752
6753
6754     if(ifx && !AOP_SIZE(result)){
6755         symbol *tlbl;
6756         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6757         /* if they are both bit variables */
6758         if (AOP_TYPE(left) == AOP_CRY &&
6759             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6760                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6761             if(AOP_TYPE(right) == AOP_LIT){
6762                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6763                 if(lit == 0L){
6764                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6765                     pic16_emitcode("cpl","c");
6766                 } else if(lit == 1L) {
6767                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6768                 } else {
6769                     pic16_emitcode("clr","c");
6770                 }
6771                 /* AOP_TYPE(right) == AOP_CRY */
6772             } else {
6773                 symbol *lbl = newiTempLabel(NULL);
6774                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6775                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6776                 pic16_emitcode("cpl","c");
6777                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6778             }
6779             /* if true label then we jump if condition
6780             supplied is true */
6781             tlbl = newiTempLabel(NULL);
6782             if ( IC_TRUE(ifx) ) {
6783                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6784                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6785             } else {
6786                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6787                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6788             }
6789             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6790
6791                 {
6792                 /* left and right are both bit variables, result is carry */
6793                         resolvedIfx rIfx;
6794               
6795                         resolveIfx(&rIfx,ifx);
6796
6797                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6798                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6799                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6800                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6801                         genSkipz2(&rIfx,0);
6802                 }
6803         } else {
6804
6805                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6806
6807                         /* They're not both bit variables. Is the right a literal? */
6808                         if(AOP_TYPE(right) == AOP_LIT) {
6809                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6810             
6811                         switch(size) {
6812
6813                                 case 1:
6814                                         switch(lit & 0xff) {
6815                                                 case 1:
6816                                                                 if ( IC_TRUE(ifx) ) {
6817                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6818                                                                         emitSKPNZ;
6819                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6820                                                                 } else {
6821                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6822                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6823                                                                 }
6824                                                                 break;
6825                                                 case 0xff:
6826                                                                 if ( IC_TRUE(ifx) ) {
6827                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6828                                                                         emitSKPNZ;
6829                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6830                                                                 } else {
6831                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6832                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6833                                                                 }
6834                                                                 break;
6835                                                 default:
6836                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6837                                                                 if(lit)
6838                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6839                                                                 genSkip(ifx,'z');
6840                                         } // switch lit
6841
6842
6843                                         /* end of size == 1 */
6844                                         break;
6845               
6846                                 case 2:
6847                                         genc16bit2lit(left,lit,offset);
6848                                         genSkip(ifx,'z');
6849                                         break;
6850                                         /* end of size == 2 */
6851
6852                                 default:
6853                                         /* size is 4 */
6854                                         if(lit==0) {
6855                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6856                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6857                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6858                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6859                                                 genSkip(ifx,'z');
6860                                         } else {
6861                                                 /* search for patterns that can be optimized */
6862
6863                                                 genc16bit2lit(left,lit,0);
6864                                                 lit >>= 16;
6865                                                 if(lit) {
6866                                                                 if(IC_TRUE(ifx))
6867                                                                 emitSKPZ; // if hi word unequal
6868                                                                 else
6869                                                                 emitSKPNZ; // if hi word equal
6870                                                                 // fail early
6871                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6872                                                         genc16bit2lit(left,lit,2);
6873                                                         genSkip(ifx,'z');
6874                                                 } else {
6875                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6876                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6877                                                         genSkip(ifx,'z');
6878                                                 }
6879                                         }
6880                                                 pic16_emitpLabel(falselbl->key);
6881                                                 break;
6882
6883                         } // switch size
6884           
6885                         ifx->generated = 1;
6886                         goto release ;
6887             
6888
6889           } else if(AOP_TYPE(right) == AOP_CRY ) {
6890             /* we know the left is not a bit, but that the right is */
6891             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6892             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6893                       pic16_popGet(AOP(right),offset));
6894             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6895
6896             /* if the two are equal, then W will be 0 and the Z bit is set
6897              * we could test Z now, or go ahead and check the high order bytes if
6898              * the variable we're comparing is larger than a byte. */
6899
6900             while(--size)
6901               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6902
6903             if ( IC_TRUE(ifx) ) {
6904               emitSKPNZ;
6905               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6906               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6907             } else {
6908               emitSKPZ;
6909               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6910               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6911             }
6912
6913           } else {
6914             /* They're both variables that are larger than bits */
6915             int s = size;
6916
6917             tlbl = newiTempLabel(NULL);
6918
6919             while(size--) {
6920               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6921               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6922
6923               if ( IC_TRUE(ifx) ) {
6924                 if(size) {
6925                   emitSKPZ;
6926                 
6927                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6928
6929                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6930                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6931                 } else {
6932                   emitSKPNZ;
6933
6934                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6935
6936
6937                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6938                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6939                 }
6940               } else {
6941                 emitSKPZ;
6942
6943                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6944
6945                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6946                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6947               }
6948               offset++;
6949             }
6950             if(s>1 && IC_TRUE(ifx)) {
6951               pic16_emitpLabel(tlbl->key);
6952               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6953             }
6954           }
6955         }
6956         /* mark the icode as generated */
6957         ifx->generated = 1;
6958         goto release ;
6959     }
6960
6961     /* if they are both bit variables */
6962     if (AOP_TYPE(left) == AOP_CRY &&
6963         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6964         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6965         if(AOP_TYPE(right) == AOP_LIT){
6966             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6967             if(lit == 0L){
6968                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6969                 pic16_emitcode("cpl","c");
6970             } else if(lit == 1L) {
6971                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6972             } else {
6973                 pic16_emitcode("clr","c");
6974             }
6975             /* AOP_TYPE(right) == AOP_CRY */
6976         } else {
6977             symbol *lbl = newiTempLabel(NULL);
6978             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6979             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6980             pic16_emitcode("cpl","c");
6981             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6982         }
6983         /* c = 1 if egal */
6984         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6985             pic16_outBitC(result);
6986             goto release ;
6987         }
6988         if (ifx) {
6989             genIfxJump (ifx,"c");
6990             goto release ;
6991         }
6992         /* if the result is used in an arithmetic operation
6993         then put the result in place */
6994         pic16_outBitC(result);
6995     } else {
6996       
6997       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6998       gencjne(left,right,result,ifx);
6999 /*
7000       if(ifx) 
7001         gencjne(left,right,newiTempLabel(NULL));
7002       else {
7003         if(IC_TRUE(ifx)->key)
7004           gencjne(left,right,IC_TRUE(ifx)->key);
7005         else
7006           gencjne(left,right,IC_FALSE(ifx)->key);
7007         ifx->generated = 1;
7008         goto release ;
7009       }
7010       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7011         pic16_aopPut(AOP(result),"a",0);
7012         goto release ;
7013       }
7014
7015       if (ifx) {
7016         genIfxJump (ifx,"a");
7017         goto release ;
7018       }
7019 */
7020       /* if the result is used in an arithmetic operation
7021          then put the result in place */
7022 /*
7023       if (AOP_TYPE(result) != AOP_CRY) 
7024         pic16_outAcc(result);
7025 */
7026       /* leave the result in acc */
7027     }
7028
7029 release:
7030     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032     pic16_freeAsmop(result,NULL,ic,TRUE);
7033 }
7034 #endif
7035
7036 /*-----------------------------------------------------------------*/
7037 /* ifxForOp - returns the icode containing the ifx for operand     */
7038 /*-----------------------------------------------------------------*/
7039 static iCode *ifxForOp ( operand *op, iCode *ic )
7040 {
7041   FENTRY2;
7042
7043     /* if true symbol then needs to be assigned */
7044     if (IS_TRUE_SYMOP(op))
7045         return NULL ;
7046
7047     /* if this has register type condition and
7048     the next instruction is ifx with the same operand
7049     and live to of the operand is upto the ifx only then */
7050     if (ic->next
7051         && ic->next->op == IFX
7052         && IC_COND(ic->next)->key == op->key
7053         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7054         ) {
7055                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7056           return ic->next;
7057     }
7058
7059     /*
7060     if (ic->next &&
7061         ic->next->op == IFX &&
7062         IC_COND(ic->next)->key == op->key) {
7063       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7064       return ic->next;
7065     }
7066     */
7067
7068     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7069     if (ic->next &&
7070         ic->next->op == IFX)
7071       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7072
7073     if (ic->next &&
7074         ic->next->op == IFX &&
7075         IC_COND(ic->next)->key == op->key) {
7076       DEBUGpic16_emitcode ("; "," key is okay");
7077       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7078                            OP_SYMBOL(op)->liveTo,
7079                            ic->next->seq);
7080     }
7081
7082 #if 0
7083     /* the code below is completely untested
7084      * it just allows ulong2fs.c compile -- VR */
7085          
7086     ic = ic->next;
7087     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7088                                         __FILE__, __FUNCTION__, __LINE__);
7089         
7090     /* if this has register type condition and
7091     the next instruction is ifx with the same operand
7092     and live to of the operand is upto the ifx only then */
7093     if (ic->next &&
7094         ic->next->op == IFX &&
7095         IC_COND(ic->next)->key == op->key &&
7096         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7097         return ic->next;
7098
7099     if (ic->next &&
7100         ic->next->op == IFX &&
7101         IC_COND(ic->next)->key == op->key) {
7102       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7103       return ic->next;
7104     }
7105
7106     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7107                                         __FILE__, __FUNCTION__, __LINE__);
7108
7109 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7110 #endif
7111
7112     return NULL;
7113 }
7114 /*-----------------------------------------------------------------*/
7115 /* genAndOp - for && operation                                     */
7116 /*-----------------------------------------------------------------*/
7117 static void genAndOp (iCode *ic)
7118 {
7119   operand *left,*right, *result;
7120 /*     symbol *tlbl; */
7121
7122     FENTRY;
7123
7124     /* note here that && operations that are in an
7125     if statement are taken away by backPatchLabels
7126     only those used in arthmetic operations remain */
7127     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7128     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7129     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7130
7131     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7132
7133     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7134     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7135     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7136
7137     /* if both are bit variables */
7138 /*     if (AOP_TYPE(left) == AOP_CRY && */
7139 /*         AOP_TYPE(right) == AOP_CRY ) { */
7140 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7141 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7142 /*         pic16_outBitC(result); */
7143 /*     } else { */
7144 /*         tlbl = newiTempLabel(NULL); */
7145 /*         pic16_toBoolean(left);     */
7146 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7147 /*         pic16_toBoolean(right); */
7148 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7149 /*         pic16_outBitAcc(result); */
7150 /*     } */
7151
7152     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7153     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7154     pic16_freeAsmop(result,NULL,ic,TRUE);
7155 }
7156
7157
7158 /*-----------------------------------------------------------------*/
7159 /* genOrOp - for || operation                                      */
7160 /*-----------------------------------------------------------------*/
7161 /*
7162   tsd pic port -
7163   modified this code, but it doesn't appear to ever get called
7164 */
7165
7166 static void genOrOp (iCode *ic)
7167 {
7168   operand *left,*right, *result;
7169   symbol *tlbl;
7170
7171     FENTRY;  
7172
7173   /* note here that || operations that are in an
7174     if statement are taken away by backPatchLabels
7175     only those used in arthmetic operations remain */
7176     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7177     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7178     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7179
7180     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7181
7182     /* if both are bit variables */
7183     if (AOP_TYPE(left) == AOP_CRY &&
7184         AOP_TYPE(right) == AOP_CRY ) {
7185       pic16_emitcode("clrc","");
7186       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7187                AOP(left)->aopu.aop_dir,
7188                AOP(left)->aopu.aop_dir);
7189       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7190                AOP(right)->aopu.aop_dir,
7191                AOP(right)->aopu.aop_dir);
7192       pic16_emitcode("setc","");
7193
7194     } else {
7195         tlbl = newiTempLabel(NULL);
7196         pic16_toBoolean(left);
7197         emitSKPZ;
7198         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7199         pic16_toBoolean(right);
7200         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7201
7202         pic16_outBitAcc(result);
7203     }
7204
7205     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7206     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7207     pic16_freeAsmop(result,NULL,ic,TRUE);            
7208 }
7209
7210 /*-----------------------------------------------------------------*/
7211 /* isLiteralBit - test if lit == 2^n                               */
7212 /*-----------------------------------------------------------------*/
7213 static int isLiteralBit(unsigned long lit)
7214 {
7215     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7216     0x100L,0x200L,0x400L,0x800L,
7217     0x1000L,0x2000L,0x4000L,0x8000L,
7218     0x10000L,0x20000L,0x40000L,0x80000L,
7219     0x100000L,0x200000L,0x400000L,0x800000L,
7220     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7221     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7222     int idx;
7223     
7224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7225     for(idx = 0; idx < 32; idx++)
7226         if(lit == pw[idx])
7227             return idx+1;
7228     return 0;
7229 }
7230
7231 /*-----------------------------------------------------------------*/
7232 /* continueIfTrue -                                                */
7233 /*-----------------------------------------------------------------*/
7234 static void continueIfTrue (iCode *ic)
7235 {
7236   FENTRY;
7237   if(IC_TRUE(ic))
7238     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7239   ic->generated = 1;
7240 }
7241
7242 /*-----------------------------------------------------------------*/
7243 /* jmpIfTrue -                                                     */
7244 /*-----------------------------------------------------------------*/
7245 static void jumpIfTrue (iCode *ic)
7246 {
7247   FENTRY;
7248   if(!IC_TRUE(ic))
7249     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7250   ic->generated = 1;
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* jmpTrueOrFalse -                                                */
7255 /*-----------------------------------------------------------------*/
7256 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7257 {
7258   // ugly but optimized by peephole
7259   FENTRY;
7260   if(IC_TRUE(ic)){
7261     symbol *nlbl = newiTempLabel(NULL);
7262       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7263       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7264       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7265       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7266   } else {
7267     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7268     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7269   }
7270   ic->generated = 1;
7271 }
7272
7273 /*-----------------------------------------------------------------*/
7274 /* genAnd  - code for and                                          */
7275 /*-----------------------------------------------------------------*/
7276 static void genAnd (iCode *ic, iCode *ifx)
7277 {
7278   operand *left, *right, *result;
7279   int size, offset=0;  
7280   unsigned long lit = 0L;
7281   int bytelit = 0;
7282   resolvedIfx rIfx;
7283
7284     FENTRY;
7285     
7286   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7287   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7288   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7289
7290   resolveIfx(&rIfx,ifx);
7291
7292   /* if left is a literal & right is not then exchange them */
7293   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7294       AOP_NEEDSACC(left)) {
7295     operand *tmp = right ;
7296     right = left;
7297     left = tmp;
7298   }
7299
7300   /* if result = right then exchange them */
7301   if(pic16_sameRegs(AOP(result),AOP(right))){
7302     operand *tmp = right ;
7303     right = left;
7304     left = tmp;
7305   }
7306
7307   /* if right is bit then exchange them */
7308   if (AOP_TYPE(right) == AOP_CRY &&
7309       AOP_TYPE(left) != AOP_CRY){
7310     operand *tmp = right ;
7311     right = left;
7312     left = tmp;
7313   }
7314   if(AOP_TYPE(right) == AOP_LIT)
7315     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7316
7317   size = AOP_SIZE(result);
7318
7319   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7320
7321   // if(bit & yy)
7322   // result = bit & yy;
7323   if (AOP_TYPE(left) == AOP_CRY){
7324     // c = bit & literal;
7325     if(AOP_TYPE(right) == AOP_LIT){
7326       if(lit & 1) {
7327         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7328           // no change
7329           goto release;
7330         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7331       } else {
7332         // bit(result) = 0;
7333         if(size && (AOP_TYPE(result) == AOP_CRY)){
7334           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7335           goto release;
7336         }
7337         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7338           jumpIfTrue(ifx);
7339           goto release;
7340         }
7341         pic16_emitcode("clr","c");
7342       }
7343     } else {
7344       if (AOP_TYPE(right) == AOP_CRY){
7345         // c = bit & bit;
7346         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7347         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7348       } else {
7349         // c = bit & val;
7350         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7351         // c = lsb
7352         pic16_emitcode("rrc","a");
7353         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7354       }
7355     }
7356     // bit = c
7357     // val = c
7358     if(size)
7359       pic16_outBitC(result);
7360     // if(bit & ...)
7361     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7362       genIfxJump(ifx, "c");           
7363     goto release ;
7364   }
7365
7366   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7367   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7368   if((AOP_TYPE(right) == AOP_LIT) &&
7369      (AOP_TYPE(result) == AOP_CRY) &&
7370      (AOP_TYPE(left) != AOP_CRY)){
7371     int posbit = isLiteralBit(lit);
7372     /* left &  2^n */
7373     if(posbit){
7374       posbit--;
7375       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7376       // bit = left & 2^n
7377       if(size)
7378         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7379       // if(left &  2^n)
7380       else{
7381         if(ifx){
7382 /*
7383           if(IC_TRUE(ifx)) {
7384             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7385             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7386           } else {
7387             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7388             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7389           }
7390 */
7391         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7392         size = AOP_SIZE(left);
7393
7394         {
7395           int bp = posbit, ofs=0;
7396           
7397             while(bp > 7) {
7398               bp -= 8;
7399               ofs++;
7400             }
7401
7402           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7403                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7404
7405         }
7406 /*
7407           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7408                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7409 */
7410           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7411           
7412           ifx->generated = 1;
7413         }
7414         goto release;
7415       }
7416     } else {
7417       symbol *tlbl = newiTempLabel(NULL);
7418       int sizel = AOP_SIZE(left);
7419
7420       if(size)
7421         emitSETC;
7422
7423       while(sizel--) {
7424         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7425
7426           /* patch provided by Aaron Colwell */
7427           if((posbit = isLiteralBit(bytelit)) != 0) {
7428               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7429                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7430                                                 (posbit-1),0, PO_GPR_REGISTER));
7431
7432               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7433 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7434           } else {
7435               if (bytelit == 0xff) {
7436                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7437                    * a peephole could optimize it out -- VR */
7438                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7439               } else {
7440                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7441                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7442               }
7443
7444               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7445                             pic16_popGetLabel(tlbl->key));
7446           }
7447         
7448 #if 0
7449           /* old code, left here for reference -- VR 09/2004 */
7450           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7451           // byte ==  2^n ?
7452           if((posbit = isLiteralBit(bytelit)) != 0)
7453             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7454           else{
7455             if(bytelit != 0x0FFL)
7456               pic16_emitcode("anl","a,%s",
7457                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7458             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7459           }
7460 #endif
7461         }
7462         offset++;
7463       }
7464       // bit = left & literal
7465       if(size) {
7466         emitCLRC;
7467         pic16_emitpLabel(tlbl->key);
7468       }
7469       // if(left & literal)
7470       else {
7471         if(ifx) {
7472           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7473           ifx->generated = 1;
7474         }
7475         pic16_emitpLabel(tlbl->key);
7476         goto release;
7477       }
7478     }
7479
7480     pic16_outBitC(result);
7481     goto release ;
7482   }
7483
7484   /* if left is same as result */
7485   if(pic16_sameRegs(AOP(result),AOP(left))){
7486     int know_W = -1;
7487     for(;size--; offset++,lit>>=8) {
7488       if(AOP_TYPE(right) == AOP_LIT){
7489         switch(lit & 0xff) {
7490         case 0x00:
7491           /*  and'ing with 0 has clears the result */
7492 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7493           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7494           break;
7495         case 0xff:
7496           /* and'ing with 0xff is a nop when the result and left are the same */
7497           break;
7498
7499         default:
7500           {
7501             int p = pic16_my_powof2( (~lit) & 0xff );
7502             if(p>=0) {
7503               /* only one bit is set in the literal, so use a bcf instruction */
7504 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7505               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7506
7507             } else {
7508               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7509               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7510               if(know_W != (lit&0xff))
7511                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7512               know_W = lit &0xff;
7513               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7514             }
7515           }    
7516         }
7517       } else {
7518         if (AOP_TYPE(left) == AOP_ACC) {
7519           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7520         } else {                    
7521           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7522           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7523
7524         }
7525       }
7526     }
7527
7528   } else {
7529     // left & result in different registers
7530     if(AOP_TYPE(result) == AOP_CRY){
7531       // result = bit
7532       // if(size), result in bit
7533       // if(!size && ifx), conditional oper: if(left & right)
7534       symbol *tlbl = newiTempLabel(NULL);
7535       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7536       if(size)
7537         pic16_emitcode("setb","c");
7538       while(sizer--){
7539         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7540         pic16_emitcode("anl","a,%s",
7541                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7542         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7543         offset++;
7544       }
7545       if(size){
7546         CLRC;
7547         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7548         pic16_outBitC(result);
7549       } else if(ifx)
7550         jmpTrueOrFalse(ifx, tlbl);
7551     } else {
7552       for(;(size--);offset++) {
7553         // normal case
7554         // result = left & right
7555         if(AOP_TYPE(right) == AOP_LIT){
7556           int t = (lit >> (offset*8)) & 0x0FFL;
7557           switch(t) { 
7558           case 0x00:
7559             pic16_emitcode("clrf","%s",
7560                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7561             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7562             break;
7563           case 0xff:
7564             pic16_emitcode("movf","%s,w",
7565                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7566             pic16_emitcode("movwf","%s",
7567                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7568             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7569             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7570             break;
7571           default:
7572             pic16_emitcode("movlw","0x%x",t);
7573             pic16_emitcode("andwf","%s,w",
7574                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7575             pic16_emitcode("movwf","%s",
7576                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7577               
7578             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7579             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7580             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7581           }
7582           continue;
7583         }
7584
7585         if (AOP_TYPE(left) == AOP_ACC) {
7586           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7587           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7588         } else {
7589           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7590           pic16_emitcode("andwf","%s,w",
7591                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7592           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7593           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7594         }
7595         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7596         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7597       }
7598     }
7599   }
7600
7601   release :
7602     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7603   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7604   pic16_freeAsmop(result,NULL,ic,TRUE);     
7605 }
7606
7607 /*-----------------------------------------------------------------*/
7608 /* genOr  - code for or                                            */
7609 /*-----------------------------------------------------------------*/
7610 static void genOr (iCode *ic, iCode *ifx)
7611 {
7612     operand *left, *right, *result;
7613     int size, offset=0;
7614     unsigned long lit = 0L;
7615
7616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7617
7618     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7619     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7620     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7621
7622     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7623
7624     /* if left is a literal & right is not then exchange them */
7625     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7626         AOP_NEEDSACC(left)) {
7627         operand *tmp = right ;
7628         right = left;
7629         left = tmp;
7630     }
7631
7632     /* if result = right then exchange them */
7633     if(pic16_sameRegs(AOP(result),AOP(right))){
7634         operand *tmp = right ;
7635         right = left;
7636         left = tmp;
7637     }
7638
7639     /* if right is bit then exchange them */
7640     if (AOP_TYPE(right) == AOP_CRY &&
7641         AOP_TYPE(left) != AOP_CRY){
7642         operand *tmp = right ;
7643         right = left;
7644         left = tmp;
7645     }
7646
7647     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7648
7649     if(AOP_TYPE(right) == AOP_LIT)
7650         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7651
7652     size = AOP_SIZE(result);
7653
7654     // if(bit | yy)
7655     // xx = bit | yy;
7656     if (AOP_TYPE(left) == AOP_CRY){
7657         if(AOP_TYPE(right) == AOP_LIT){
7658             // c = bit & literal;
7659             if(lit){
7660                 // lit != 0 => result = 1
7661                 if(AOP_TYPE(result) == AOP_CRY){
7662                   if(size)
7663                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7664                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7665                   //     AOP(result)->aopu.aop_dir,
7666                   //     AOP(result)->aopu.aop_dir);
7667                     else if(ifx)
7668                         continueIfTrue(ifx);
7669                     goto release;
7670                 }
7671             } else {
7672                 // lit == 0 => result = left
7673                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7674                     goto release;
7675                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7676             }
7677         } else {
7678             if (AOP_TYPE(right) == AOP_CRY){
7679               if(pic16_sameRegs(AOP(result),AOP(left))){
7680                 // c = bit | bit;
7681                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7682                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7683                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7684
7685                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7686                          AOP(result)->aopu.aop_dir,
7687                          AOP(result)->aopu.aop_dir);
7688                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7689                          AOP(right)->aopu.aop_dir,
7690                          AOP(right)->aopu.aop_dir);
7691                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7692                          AOP(result)->aopu.aop_dir,
7693                          AOP(result)->aopu.aop_dir);
7694               } else {
7695                 if( AOP_TYPE(result) == AOP_ACC) {
7696                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7697                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7698                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7699                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7700
7701                 } else {
7702
7703                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7704                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7705                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7706                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7707
7708                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7709                                  AOP(result)->aopu.aop_dir,
7710                                  AOP(result)->aopu.aop_dir);
7711                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7712                                  AOP(right)->aopu.aop_dir,
7713                                  AOP(right)->aopu.aop_dir);
7714                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7715                                  AOP(left)->aopu.aop_dir,
7716                                  AOP(left)->aopu.aop_dir);
7717                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7718                                  AOP(result)->aopu.aop_dir,
7719                                  AOP(result)->aopu.aop_dir);
7720                 }
7721               }
7722             } else {
7723                 // c = bit | val;
7724                 symbol *tlbl = newiTempLabel(NULL);
7725                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7726
7727
7728                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7729                 if( AOP_TYPE(right) == AOP_ACC) {
7730                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7731                   emitSKPNZ;
7732                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7733                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7734                 }
7735
7736
7737
7738                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7739                     pic16_emitcode(";XXX setb","c");
7740                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7741                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7742                 pic16_toBoolean(right);
7743                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7744                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7745                     jmpTrueOrFalse(ifx, tlbl);
7746                     goto release;
7747                 } else {
7748                     CLRC;
7749                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7750                 }
7751             }
7752         }
7753         // bit = c
7754         // val = c
7755         if(size)
7756             pic16_outBitC(result);
7757         // if(bit | ...)
7758         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7759             genIfxJump(ifx, "c");           
7760         goto release ;
7761     }
7762
7763     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7764     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7765     if((AOP_TYPE(right) == AOP_LIT) &&
7766        (AOP_TYPE(result) == AOP_CRY) &&
7767        (AOP_TYPE(left) != AOP_CRY)){
7768         if(lit){
7769           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7770             // result = 1
7771             if(size)
7772                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7773             else 
7774                 continueIfTrue(ifx);
7775             goto release;
7776         } else {
7777           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7778             // lit = 0, result = boolean(left)
7779             if(size)
7780                 pic16_emitcode(";XXX setb","c");
7781             pic16_toBoolean(right);
7782             if(size){
7783                 symbol *tlbl = newiTempLabel(NULL);
7784                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7785                 CLRC;
7786                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7787             } else {
7788                 genIfxJump (ifx,"a");
7789                 goto release;
7790             }
7791         }
7792         pic16_outBitC(result);
7793         goto release ;
7794     }
7795
7796     /* if left is same as result */
7797     if(pic16_sameRegs(AOP(result),AOP(left))){
7798       int know_W = -1;
7799       for(;size--; offset++,lit>>=8) {
7800         if(AOP_TYPE(right) == AOP_LIT){
7801           if((lit & 0xff) == 0)
7802             /*  or'ing with 0 has no effect */
7803             continue;
7804           else {
7805             int p = pic16_my_powof2(lit & 0xff);
7806             if(p>=0) {
7807               /* only one bit is set in the literal, so use a bsf instruction */
7808               pic16_emitpcode(POC_BSF,
7809                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7810             } else {
7811               if(know_W != (lit & 0xff))
7812                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7813               know_W = lit & 0xff;
7814               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7815             }
7816                     
7817           }
7818         } else {
7819           if (AOP_TYPE(left) == AOP_ACC) {
7820             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7821 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7822           } else {                  
7823             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7824             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7825
7826 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7827 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7828
7829           }
7830         }
7831       }
7832     } else {
7833         // left & result in different registers
7834         if(AOP_TYPE(result) == AOP_CRY){
7835             // result = bit
7836             // if(size), result in bit
7837             // if(!size && ifx), conditional oper: if(left | right)
7838             symbol *tlbl = newiTempLabel(NULL);
7839             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7840             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7841
7842
7843             if(size)
7844                 pic16_emitcode(";XXX setb","c");
7845             while(sizer--){
7846                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7847                 pic16_emitcode(";XXX orl","a,%s",
7848                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7849                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7850                 offset++;
7851             }
7852             if(size){
7853                 CLRC;
7854                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7855                 pic16_outBitC(result);
7856             } else if(ifx)
7857                 jmpTrueOrFalse(ifx, tlbl);
7858         } else for(;(size--);offset++){
7859           // normal case
7860           // result = left & right
7861           if(AOP_TYPE(right) == AOP_LIT){
7862             int t = (lit >> (offset*8)) & 0x0FFL;
7863             switch(t) { 
7864             case 0x00:
7865               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7866               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7867
7868 //            pic16_emitcode("movf","%s,w",
7869 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7870 //            pic16_emitcode("movwf","%s",
7871 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7872               break;
7873             default:
7874               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7875               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7876               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7877
7878 //            pic16_emitcode("movlw","0x%x",t);
7879 //            pic16_emitcode("iorwf","%s,w",
7880 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7881 //            pic16_emitcode("movwf","%s",
7882 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7883               
7884             }
7885             continue;
7886           }
7887
7888           // faster than result <- left, anl result,right
7889           // and better if result is SFR
7890           if (AOP_TYPE(left) == AOP_ACC) {
7891             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7892 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7893           } else {
7894             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7895             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7896
7897 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7898 //          pic16_emitcode("iorwf","%s,w",
7899 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7900           }
7901           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7902 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7903         }
7904     }
7905
7906 release :
7907     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7908     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7909     pic16_freeAsmop(result,NULL,ic,TRUE);     
7910 }
7911
7912 /*-----------------------------------------------------------------*/
7913 /* genXor - code for xclusive or                                   */
7914 /*-----------------------------------------------------------------*/
7915 static void genXor (iCode *ic, iCode *ifx)
7916 {
7917   operand *left, *right, *result;
7918   int size, offset=0;
7919   unsigned long lit = 0L;
7920
7921   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7922
7923   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7924   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7925   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7926
7927   /* if left is a literal & right is not ||
7928      if left needs acc & right does not */
7929   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7930       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7931     operand *tmp = right ;
7932     right = left;
7933     left = tmp;
7934   }
7935
7936   /* if result = right then exchange them */
7937   if(pic16_sameRegs(AOP(result),AOP(right))){
7938     operand *tmp = right ;
7939     right = left;
7940     left = tmp;
7941   }
7942
7943   /* if right is bit then exchange them */
7944   if (AOP_TYPE(right) == AOP_CRY &&
7945       AOP_TYPE(left) != AOP_CRY){
7946     operand *tmp = right ;
7947     right = left;
7948     left = tmp;
7949   }
7950   if(AOP_TYPE(right) == AOP_LIT)
7951     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7952
7953   size = AOP_SIZE(result);
7954
7955   // if(bit ^ yy)
7956   // xx = bit ^ yy;
7957   if (AOP_TYPE(left) == AOP_CRY){
7958     if(AOP_TYPE(right) == AOP_LIT){
7959       // c = bit & literal;
7960       if(lit>>1){
7961         // lit>>1  != 0 => result = 1
7962         if(AOP_TYPE(result) == AOP_CRY){
7963           if(size)
7964             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7965             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7966           else if(ifx)
7967             continueIfTrue(ifx);
7968           goto release;
7969         }
7970         pic16_emitcode("setb","c");
7971       } else{
7972         // lit == (0 or 1)
7973         if(lit == 0){
7974           // lit == 0, result = left
7975           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7976             goto release;
7977           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7978         } else{
7979           // lit == 1, result = not(left)
7980           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7981             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7982             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7983             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7984             goto release;
7985           } else {
7986             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7987             pic16_emitcode("cpl","c");
7988           }
7989         }
7990       }
7991
7992     } else {
7993       // right != literal
7994       symbol *tlbl = newiTempLabel(NULL);
7995       if (AOP_TYPE(right) == AOP_CRY){
7996         // c = bit ^ bit;
7997         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7998       }
7999       else{
8000         int sizer = AOP_SIZE(right);
8001         // c = bit ^ val
8002         // if val>>1 != 0, result = 1
8003         pic16_emitcode("setb","c");
8004         while(sizer){
8005           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8006           if(sizer == 1)
8007             // test the msb of the lsb
8008             pic16_emitcode("anl","a,#0xfe");
8009           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8010           sizer--;
8011         }
8012         // val = (0,1)
8013         pic16_emitcode("rrc","a");
8014       }
8015       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8016       pic16_emitcode("cpl","c");
8017       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8018     }
8019     // bit = c
8020     // val = c
8021     if(size)
8022       pic16_outBitC(result);
8023     // if(bit | ...)
8024     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8025       genIfxJump(ifx, "c");           
8026     goto release ;
8027   }
8028
8029   if(pic16_sameRegs(AOP(result),AOP(left))){
8030     /* if left is same as result */
8031     for(;size--; offset++) {
8032       if(AOP_TYPE(right) == AOP_LIT){
8033         int t  = (lit >> (offset*8)) & 0x0FFL;
8034         if(t == 0x00L)
8035           continue;
8036         else
8037           if (IS_AOP_PREG(left)) {
8038             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8039             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8040             pic16_aopPut(AOP(result),"a",offset);
8041           } else {
8042             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8043             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8044             pic16_emitcode("xrl","%s,%s",
8045                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8046                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8047           }
8048       } else {
8049         if (AOP_TYPE(left) == AOP_ACC)
8050           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8051         else {
8052           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8053           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8054 /*
8055           if (IS_AOP_PREG(left)) {
8056             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8057             pic16_aopPut(AOP(result),"a",offset);
8058           } else
8059             pic16_emitcode("xrl","%s,a",
8060                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8061 */
8062         }
8063       }
8064     }
8065   } else {
8066     // left & result in different registers
8067     if(AOP_TYPE(result) == AOP_CRY){
8068       // result = bit
8069       // if(size), result in bit
8070       // if(!size && ifx), conditional oper: if(left ^ right)
8071       symbol *tlbl = newiTempLabel(NULL);
8072       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8073       if(size)
8074         pic16_emitcode("setb","c");
8075       while(sizer--){
8076         if((AOP_TYPE(right) == AOP_LIT) &&
8077            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8078           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8079         } else {
8080           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8081           pic16_emitcode("xrl","a,%s",
8082                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8083         }
8084         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8085         offset++;
8086       }
8087       if(size){
8088         CLRC;
8089         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8090         pic16_outBitC(result);
8091       } else if(ifx)
8092         jmpTrueOrFalse(ifx, tlbl);
8093     } else for(;(size--);offset++){
8094       // normal case
8095       // result = left & right
8096       if(AOP_TYPE(right) == AOP_LIT){
8097         int t = (lit >> (offset*8)) & 0x0FFL;
8098         switch(t) { 
8099         case 0x00:
8100           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8101           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8102           pic16_emitcode("movf","%s,w",
8103                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8104           pic16_emitcode("movwf","%s",
8105                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8106           break;
8107         case 0xff:
8108           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8109           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8110           pic16_emitcode("comf","%s,w",
8111                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8112           pic16_emitcode("movwf","%s",
8113                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8114           break;
8115         default:
8116           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8117           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8118           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8119           pic16_emitcode("movlw","0x%x",t);
8120           pic16_emitcode("xorwf","%s,w",
8121                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8122           pic16_emitcode("movwf","%s",
8123                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8124
8125         }
8126         continue;
8127       }
8128
8129       // faster than result <- left, anl result,right
8130       // and better if result is SFR
8131       if (AOP_TYPE(left) == AOP_ACC) {
8132         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8133         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8134       } else {
8135         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8136         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8137         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8138         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8139       }
8140       if ( AOP_TYPE(result) != AOP_ACC){
8141         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8142         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8143       }
8144     }
8145   }
8146
8147   release :
8148     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8149   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8150   pic16_freeAsmop(result,NULL,ic,TRUE);     
8151 }
8152
8153 /*-----------------------------------------------------------------*/
8154 /* genInline - write the inline code out                           */
8155 /*-----------------------------------------------------------------*/
8156 static void genInline (iCode *ic)
8157 {
8158   char *buffer, *bp, *bp1;
8159     
8160         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8161
8162         _G.inLine += (!options.asmpeep);
8163
8164         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8165         strcpy(buffer,IC_INLINE(ic));
8166         
8167         while((bp1=strstr(bp, "\\n"))) {
8168           *bp1++ = '\n';
8169           *bp1++ = ' ';
8170           bp = bp1;
8171         }
8172         bp = bp1 = buffer;
8173
8174 #if 0
8175   /* This is an experimental code for #pragma inline
8176      and is temporarily disabled for 2.5.0 release */
8177         if(asmInlineMap)
8178         {
8179           symbol *sym;
8180           char *s;
8181           char *cbuf;
8182           int cblen;
8183
8184             cbuf = Safe_strdup(buffer);
8185             cblen = strlen(buffer)+1;
8186             memset(cbuf, 0, cblen);
8187
8188             bp = buffer;
8189             bp1 = cbuf;
8190             while(*bp) {
8191               if(*bp != '%')*bp1++ = *bp++;
8192               else {
8193                 int i;
8194
8195                   bp++;
8196                   i = *bp - '0';
8197                   if(i>elementsInSet(asmInlineMap))break;
8198                   
8199                   bp++;
8200                   s = indexSet(asmInlineMap, i);
8201                   DEBUGpc("searching symbol s = `%s'", s);
8202                   sym = findSym(SymbolTab, NULL, s);
8203
8204                   if(sym->reqv) {
8205                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8206                   } else {
8207                     strcat(bp1, sym->rname);
8208                   }
8209                   
8210                   while(*bp1)bp1++;
8211               }
8212               
8213               if(strlen(bp1) > cblen - 16) {
8214                 int i = strlen(cbuf);
8215                 cblen += 50;
8216                 cbuf = realloc(cbuf, cblen);
8217                 memset(cbuf+i, 0, 50);
8218                 bp1 = cbuf + i;
8219               }
8220             }
8221             
8222             free(buffer);
8223             buffer = Safe_strdup( cbuf );
8224             free(cbuf);
8225             
8226             bp = bp1 = buffer;
8227         }
8228 #endif  /* 0 */
8229
8230         /* emit each line as a code */
8231         while (*bp) {
8232                 if (*bp == '\n') {
8233                         *bp++ = '\0';
8234
8235                         if(*bp1)
8236                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8237                         bp1 = bp;
8238                 } else {
8239                         if (*bp == ':') {
8240                                 bp++;
8241                                 *bp = '\0';
8242                                 bp++;
8243
8244                                 /* print label, use this special format with NULL directive
8245                                  * to denote that the argument should not be indented with tab */
8246                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8247                                 bp1 = bp;
8248                         } if (*bp == ';') {
8249                                 /* advance to end of line (prevent splitting of comments at ':' */
8250                                 while (*bp && *bp != '\n') {
8251                                         bp++;
8252                                 } // while
8253                         } else
8254                                 bp++;
8255                 }
8256         }
8257
8258         if ((bp1 != bp) && *bp1)
8259                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8260
8261
8262     Safe_free(buffer);
8263
8264     _G.inLine -= (!options.asmpeep);
8265 }
8266
8267 /*-----------------------------------------------------------------*/
8268 /* genRRC - rotate right with carry                                */
8269 /*-----------------------------------------------------------------*/
8270 static void genRRC (iCode *ic)
8271 {
8272   operand *left , *result ;
8273   int size, offset = 0, same;
8274
8275   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8276
8277   /* rotate right with carry */
8278   left = IC_LEFT(ic);
8279   result=IC_RESULT(ic);
8280   pic16_aopOp (left,ic,FALSE);
8281   pic16_aopOp (result,ic,TRUE);
8282
8283   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8284
8285   same = pic16_sameRegs(AOP(result),AOP(left));
8286
8287   size = AOP_SIZE(result);    
8288
8289   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8290
8291   /* get the lsb and put it into the carry */
8292   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8293
8294   offset = 0 ;
8295
8296   while(size--) {
8297
8298     if(same) {
8299       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8300     } else {
8301       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8302       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8303     }
8304
8305     offset++;
8306   }
8307
8308   pic16_freeAsmop(left,NULL,ic,TRUE);
8309   pic16_freeAsmop(result,NULL,ic,TRUE);
8310 }
8311
8312 /*-----------------------------------------------------------------*/
8313 /* genRLC - generate code for rotate left with carry               */
8314 /*-----------------------------------------------------------------*/
8315 static void genRLC (iCode *ic)
8316 {    
8317   operand *left , *result ;
8318   int size, offset = 0;
8319   int same;
8320
8321   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8322   /* rotate right with carry */
8323   left = IC_LEFT(ic);
8324   result=IC_RESULT(ic);
8325   pic16_aopOp (left,ic,FALSE);
8326   pic16_aopOp (result,ic,TRUE);
8327
8328   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8329
8330   same = pic16_sameRegs(AOP(result),AOP(left));
8331
8332   /* move it to the result */
8333   size = AOP_SIZE(result);    
8334
8335   /* get the msb and put it into the carry */
8336   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8337
8338   offset = 0 ;
8339
8340   while(size--) {
8341
8342     if(same) {
8343       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8344     } else {
8345       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8346       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8347     }
8348
8349     offset++;
8350   }
8351
8352
8353   pic16_freeAsmop(left,NULL,ic,TRUE);
8354   pic16_freeAsmop(result,NULL,ic,TRUE);
8355 }
8356
8357
8358 /* gpasm can get the highest order bit with HIGH/UPPER
8359  * so the following probably is not needed -- VR */
8360  
8361 /*-----------------------------------------------------------------*/
8362 /* genGetHbit - generates code get highest order bit               */
8363 /*-----------------------------------------------------------------*/
8364 static void genGetHbit (iCode *ic)
8365 {
8366     operand *left, *result;
8367     left = IC_LEFT(ic);
8368     result=IC_RESULT(ic);
8369     pic16_aopOp (left,ic,FALSE);
8370     pic16_aopOp (result,ic,FALSE);
8371
8372     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8373     /* get the highest order byte into a */
8374     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8375     if(AOP_TYPE(result) == AOP_CRY){
8376         pic16_emitcode("rlc","a");
8377         pic16_outBitC(result);
8378     }
8379     else{
8380         pic16_emitcode("rl","a");
8381         pic16_emitcode("anl","a,#0x01");
8382         pic16_outAcc(result);
8383     }
8384
8385
8386     pic16_freeAsmop(left,NULL,ic,TRUE);
8387     pic16_freeAsmop(result,NULL,ic,TRUE);
8388 }
8389
8390 #if 0
8391 /*-----------------------------------------------------------------*/
8392 /* AccRol - rotate left accumulator by known count                 */
8393 /*-----------------------------------------------------------------*/
8394 static void AccRol (int shCount)
8395 {
8396     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8397     shCount &= 0x0007;              // shCount : 0..7
8398     switch(shCount){
8399         case 0 :
8400             break;
8401         case 1 :
8402             pic16_emitcode("rl","a");
8403             break;
8404         case 2 :
8405             pic16_emitcode("rl","a");
8406             pic16_emitcode("rl","a");
8407             break;
8408         case 3 :
8409             pic16_emitcode("swap","a");
8410             pic16_emitcode("rr","a");
8411             break;
8412         case 4 :
8413             pic16_emitcode("swap","a");
8414             break;
8415         case 5 :
8416             pic16_emitcode("swap","a");
8417             pic16_emitcode("rl","a");
8418             break;
8419         case 6 :
8420             pic16_emitcode("rr","a");
8421             pic16_emitcode("rr","a");
8422             break;
8423         case 7 :
8424             pic16_emitcode("rr","a");
8425             break;
8426     }
8427 }
8428 #endif
8429
8430 /*-----------------------------------------------------------------*/
8431 /* AccLsh - left shift accumulator by known count                  */
8432 /*-----------------------------------------------------------------*/
8433 static void AccLsh (int shCount, int doMask)
8434 {
8435         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8436         switch(shCount){
8437                 case 0 :
8438                         return;
8439                         break;
8440                 case 1 :
8441                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8442                         break;
8443                 case 2 :
8444                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8446                         break;
8447                 case 3 :
8448                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8450                         break;
8451                 case 4 :
8452                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8453                         break;
8454                 case 5 :
8455                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8456                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8457                         break;
8458                 case 6 :
8459                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8461                         break;
8462                 case 7 :
8463                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464                         break;
8465         }
8466         if (doMask) {
8467                 /* no masking is required in genPackBits */
8468                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8469         }
8470 }
8471
8472 /*-----------------------------------------------------------------*/
8473 /* AccRsh - right shift accumulator by known count                 */
8474 /*-----------------------------------------------------------------*/
8475 static void AccRsh (int shCount, int andmask)
8476 {
8477         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8478         switch(shCount){
8479                 case 0 :
8480                         return; break;
8481                 case 1 :
8482                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8483                         break;
8484                 case 2 :
8485                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8486                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487                         break;
8488                 case 3 :
8489                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8490                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8491                         break;
8492                 case 4 :
8493                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8494                         break;
8495                 case 5 :
8496                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8497                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8498                         break;
8499                 case 6 :
8500                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8501                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502                         break;
8503                 case 7 :
8504                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505                         break;
8506         }
8507         
8508         if(andmask)
8509                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8510         else
8511                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8512 }
8513
8514 #if 0
8515 /*-----------------------------------------------------------------*/
8516 /* AccSRsh - signed right shift accumulator by known count                 */
8517 /*-----------------------------------------------------------------*/
8518 static void AccSRsh (int shCount)
8519 {
8520     symbol *tlbl ;
8521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8522     if(shCount != 0){
8523         if(shCount == 1){
8524             pic16_emitcode("mov","c,acc.7");
8525             pic16_emitcode("rrc","a");
8526         } else if(shCount == 2){
8527             pic16_emitcode("mov","c,acc.7");
8528             pic16_emitcode("rrc","a");
8529             pic16_emitcode("mov","c,acc.7");
8530             pic16_emitcode("rrc","a");
8531         } else {
8532             tlbl = newiTempLabel(NULL);
8533             /* rotate right accumulator */
8534             AccRol(8 - shCount);
8535             /* and kill the higher order bits */
8536             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8537             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8538             pic16_emitcode("orl","a,#0x%02x",
8539                      (unsigned char)~SRMask[shCount]);
8540             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8541         }
8542     }
8543 }
8544 #endif
8545
8546 /*-----------------------------------------------------------------*/
8547 /* shiftR1Left2Result - shift right one byte from left to result   */
8548 /*-----------------------------------------------------------------*/
8549 static void shiftR1Left2ResultSigned (operand *left, int offl,
8550                                 operand *result, int offr,
8551                                 int shCount)
8552 {
8553   int same;
8554
8555   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8556
8557   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8558
8559   switch(shCount) {
8560   case 1:
8561     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8562     if(same) 
8563       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8564     else {
8565       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8566       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8567     }
8568
8569     break;
8570   case 2:
8571
8572     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8573     if(same) 
8574       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8575     else {
8576       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8577       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8578     }
8579     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8580     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8581
8582     break;
8583
8584   case 3:
8585     if(same)
8586       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8587     else {
8588       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8589       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8590     }
8591
8592     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8593     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8594     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8595
8596     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8597     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8598
8599     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8600     break;
8601
8602   case 4:
8603     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8604     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8605     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8606     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8607     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8608     break;
8609   case 5:
8610     if(same) {
8611       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8612     } else {
8613       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8614       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8615     }
8616     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8617     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8618     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8619     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8620     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8621     break;
8622
8623   case 6:
8624     if(same) {
8625       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8626       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8627       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8628       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8629       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8630       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8631     } else {
8632       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8633       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8634       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8635       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8636       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8637     }
8638     break;
8639
8640   case 7:
8641     if(same) {
8642       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8643       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8644       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8646     } else {
8647       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8648       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8649       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8650     }
8651
8652   default:
8653     break;
8654   }
8655 }
8656
8657 /*-----------------------------------------------------------------*/
8658 /* shiftR1Left2Result - shift right one byte from left to result   */
8659 /*-----------------------------------------------------------------*/
8660 static void shiftR1Left2Result (operand *left, int offl,
8661                                 operand *result, int offr,
8662                                 int shCount, int sign)
8663 {
8664   int same;
8665
8666   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8667
8668   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8669
8670   /* Copy the msb into the carry if signed. */
8671   if(sign) {
8672     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8673     return;
8674   }
8675
8676
8677
8678   switch(shCount) {
8679   case 1:
8680     emitCLRC;
8681     if(same) 
8682       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8683     else {
8684       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8685       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8686     }
8687     break;
8688   case 2:
8689     emitCLRC;
8690     if(same) {
8691       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8692     } else {
8693       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8694       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8695     }
8696     emitCLRC;
8697     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8698
8699     break;
8700   case 3:
8701     if(same)
8702       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8703     else {
8704       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8706     }
8707
8708     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8709     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8710     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8711     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8712     break;
8713       
8714   case 4:
8715     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8716     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8717     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8718     break;
8719
8720   case 5:
8721     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8722     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8723     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8724     //emitCLRC;
8725     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8726
8727     break;
8728   case 6:
8729
8730     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8731     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8732     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8733     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8734     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8735     break;
8736
8737   case 7:
8738
8739     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8740     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8741     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8742
8743     break;
8744
8745   default:
8746     break;
8747   }
8748 }
8749
8750 /*-----------------------------------------------------------------*/
8751 /* shiftL1Left2Result - shift left one byte from left to result    */
8752 /*-----------------------------------------------------------------*/
8753 static void shiftL1Left2Result (operand *left, int offl,
8754                                 operand *result, int offr, int shCount)
8755 {
8756   int same;
8757
8758   //    char *l;
8759   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8760
8761   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8762   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8763     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8764     //    MOVA(l);
8765     /* shift left accumulator */
8766     //AccLsh(shCount, 1); // don't comment out just yet...
8767   //    pic16_aopPut(AOP(result),"a",offr);
8768
8769   switch(shCount) {
8770   case 1:
8771     /* Shift left 1 bit position */
8772     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8773     if(same) {
8774       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8775     } else {
8776       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8777       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8778     }
8779     break;
8780   case 2:
8781     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8783     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8785     break;
8786   case 3:
8787     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8788     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8789     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8790     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8791     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8792     break;
8793   case 4:
8794     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8795     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8796     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8797     break;
8798   case 5:
8799     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8800     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8801     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8802     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8803     break;
8804   case 6:
8805     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8806     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8807     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8808     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8809     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8810     break;
8811   case 7:
8812     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8813     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8814     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8815     break;
8816
8817   default:
8818     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8819   }
8820
8821 }
8822
8823 /*-----------------------------------------------------------------*/
8824 /* movLeft2Result - move byte from left to result                  */
8825 /*-----------------------------------------------------------------*/
8826 static void movLeft2Result (operand *left, int offl,
8827                             operand *result, int offr)
8828 {
8829   char *l;
8830   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8831   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8832     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8833
8834     if (*l == '@' && (IS_AOP_PREG(result))) {
8835       pic16_emitcode("mov","a,%s",l);
8836       pic16_aopPut(AOP(result),"a",offr);
8837     } else {
8838       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8839       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8840     }
8841   }
8842 }
8843
8844 /*-----------------------------------------------------------------*/
8845 /* shiftL2Left2Result - shift left two bytes from left to result   */
8846 /*-----------------------------------------------------------------*/
8847 static void shiftL2Left2Result (operand *left, int offl,
8848                                 operand *result, int offr, int shCount)
8849 {
8850   int same = pic16_sameRegs(AOP(result), AOP(left));
8851   int i;
8852
8853   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8854
8855   if (same && (offl != offr)) { // shift bytes
8856     if (offr > offl) {
8857        for(i=1;i>-1;i--) {
8858          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8859          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8860        }
8861     } else { // just treat as different later on
8862                 same = 0;
8863     }
8864   }
8865
8866   if(same) {
8867     switch(shCount) {
8868     case 0:
8869       break;
8870     case 1:
8871     case 2:
8872     case 3:
8873
8874       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8875       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8876       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8877
8878       while(--shCount) {
8879                 emitCLRC;
8880                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8881                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8882       }
8883
8884       break;
8885     case 4:
8886     case 5:
8887       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8888       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8889       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8890       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8891       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8892       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8893       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8894       if(shCount >=5) {
8895                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8896                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8897       }
8898       break;
8899     case 6:
8900       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8901       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8902       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8903       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8904       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8905       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8906       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8907       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8909       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8910       break;
8911     case 7:
8912       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8913       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8914       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8915       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8916       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8917     }
8918
8919   } else {
8920     switch(shCount) {
8921     case 0:
8922       break;
8923     case 1:
8924     case 2:
8925     case 3:
8926       /* note, use a mov/add for the shift since the mov has a
8927          chance of getting optimized out */
8928       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8929       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8930       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8931       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8932       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8933
8934       while(--shCount) {
8935                 emitCLRC;
8936                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8937                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8938       }
8939       break;
8940
8941     case 4:
8942     case 5:
8943       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8944       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8945       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8946       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8947       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8948       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8949       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8950       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8951
8952
8953       if(shCount == 5) {
8954                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8955                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8956       }
8957       break;
8958     case 6:
8959       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8960       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8961       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8962       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8963
8964       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8965       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8967       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8968       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8969       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8972       break;
8973     case 7:
8974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8975       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8976       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8977       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8978       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8979     }
8980   }
8981
8982 }
8983 /*-----------------------------------------------------------------*/
8984 /* shiftR2Left2Result - shift right two bytes from left to result  */
8985 /*-----------------------------------------------------------------*/
8986 static void shiftR2Left2Result (operand *left, int offl,
8987                                 operand *result, int offr,
8988                                 int shCount, int sign)
8989 {
8990   int same = pic16_sameRegs(AOP(result), AOP(left));
8991   int i;
8992   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8993
8994   if (same && (offl != offr)) { // shift right bytes
8995     if (offr < offl) {
8996        for(i=0;i<2;i++) {
8997          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8998          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8999        }
9000     } else { // just treat as different later on
9001                 same = 0;
9002     }
9003   }
9004
9005   switch(shCount) {
9006   case 0:
9007     break;
9008   case 1:
9009   case 2:
9010   case 3:
9011     if(sign)
9012       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9013     else
9014       emitCLRC;
9015
9016     if(same) {
9017       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9018       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9019     } else {
9020       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9021       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9022       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9023       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9024     }
9025
9026     while(--shCount) {
9027       if(sign)
9028                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9029       else
9030                 emitCLRC;
9031       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9032       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9033     }
9034     break;
9035   case 4:
9036   case 5:
9037     if(same) {
9038
9039       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9040       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9041       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9042
9043       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9045       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9046       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9047     } else {
9048       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9049       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9050       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9051
9052       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9053       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9054       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9055       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9056       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9057     }
9058
9059     if(shCount >=5) {
9060       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9061       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9062     }
9063
9064     if(sign) {
9065       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9066       pic16_emitpcode(POC_BTFSC, 
9067                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9068       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9069     }
9070
9071     break;
9072
9073   case 6:
9074     if(same) {
9075
9076       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9077       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9078
9079       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9080       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9081       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9082       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9083       if(sign) {
9084         pic16_emitpcode(POC_BTFSC, 
9085                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9086         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9087       }
9088       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9089       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9090       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9091       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9092     } else {
9093       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9094       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9095       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9096       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9097       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9098       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9099       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9100       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9101       if(sign) {
9102         pic16_emitpcode(POC_BTFSC, 
9103                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9104         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9105       }
9106       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9107       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9108
9109         
9110     }
9111
9112     break;
9113   case 7:
9114     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9115     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9116     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9117     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9118     if(sign) {
9119       emitSKPNC;
9120       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9121     } else 
9122       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9123   }
9124 }
9125
9126
9127 /*-----------------------------------------------------------------*/
9128 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9129 /*-----------------------------------------------------------------*/
9130 static void shiftLLeftOrResult (operand *left, int offl,
9131                                 operand *result, int offr, int shCount)
9132 {
9133     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9134
9135     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9136     /* shift left accumulator */
9137     AccLsh(shCount, 1);
9138     /* or with result */
9139     /* back to result */
9140     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9141 }
9142
9143 /*-----------------------------------------------------------------*/
9144 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9145 /*-----------------------------------------------------------------*/
9146 static void shiftRLeftOrResult (operand *left, int offl,
9147                                 operand *result, int offr, int shCount)
9148 {
9149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9150     
9151     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9152     /* shift right accumulator */
9153     AccRsh(shCount, 1);
9154     /* or with result */
9155     /* back to result */
9156     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9157 }
9158
9159 /*-----------------------------------------------------------------*/
9160 /* genlshOne - left shift a one byte quantity by known count       */
9161 /*-----------------------------------------------------------------*/
9162 static void genlshOne (operand *result, operand *left, int shCount)
9163 {       
9164     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9165     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9166 }
9167
9168 /*-----------------------------------------------------------------*/
9169 /* genlshTwo - left shift two bytes by known amount != 0           */
9170 /*-----------------------------------------------------------------*/
9171 static void genlshTwo (operand *result,operand *left, int shCount)
9172 {
9173     int size;
9174     
9175     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9176     size = pic16_getDataSize(result);
9177
9178     /* if shCount >= 8 */
9179     if (shCount >= 8) {
9180         shCount -= 8 ;
9181
9182         if (size > 1){
9183             if (shCount)
9184                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9185             else 
9186                 movLeft2Result(left, LSB, result, MSB16);
9187         }
9188         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9189     }
9190
9191     /*  1 <= shCount <= 7 */
9192     else {  
9193         if(size == 1)
9194             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9195         else 
9196             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9197     }
9198 }
9199
9200 /*-----------------------------------------------------------------*/
9201 /* shiftLLong - shift left one long from left to result            */
9202 /* offr = LSB or MSB16                                             */
9203 /*-----------------------------------------------------------------*/
9204 static void shiftLLong (operand *left, operand *result, int offr )
9205 {
9206     int size = AOP_SIZE(result);
9207     int same = pic16_sameRegs(AOP(left),AOP(result));
9208         int i;
9209
9210     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9211
9212         if (same && (offr == MSB16)) { //shift one byte
9213                 for(i=size-1;i>=MSB16;i--) {
9214                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9215                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9216                 }
9217         } else {
9218                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9219         }
9220         
9221     if (size > LSB+offr ){
9222                 if (same) {
9223                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9224                 } else {
9225                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9226                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9227                 }
9228          }
9229
9230     if(size > MSB16+offr){
9231                 if (same) {
9232                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9233                 } else {
9234                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9235                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9236                 }
9237     }
9238
9239     if(size > MSB24+offr){
9240                 if (same) {
9241                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9242                 } else {
9243                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9244                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9245                 }
9246     }
9247
9248     if(size > MSB32+offr){
9249                 if (same) {
9250                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9251                 } else {
9252                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9253                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9254                 }
9255     }
9256     if(offr != LSB)
9257                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9258
9259 }
9260
9261 /*-----------------------------------------------------------------*/
9262 /* genlshFour - shift four byte by a known amount != 0             */
9263 /*-----------------------------------------------------------------*/
9264 static void genlshFour (operand *result, operand *left, int shCount)
9265 {
9266     int size;
9267
9268     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9269     size = AOP_SIZE(result);
9270
9271     /* if shifting more that 3 bytes */
9272     if (shCount >= 24 ) {
9273         shCount -= 24;
9274         if (shCount)
9275             /* lowest order of left goes to the highest
9276             order of the destination */
9277             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9278         else
9279             movLeft2Result(left, LSB, result, MSB32);
9280
9281                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9282                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9283                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9284
9285         return;
9286     }
9287
9288     /* more than two bytes */
9289     else if ( shCount >= 16 ) {
9290         /* lower order two bytes goes to higher order two bytes */
9291         shCount -= 16;
9292         /* if some more remaining */
9293         if (shCount)
9294             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9295         else {
9296             movLeft2Result(left, MSB16, result, MSB32);
9297             movLeft2Result(left, LSB, result, MSB24);
9298         }
9299                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9300                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9301         return;
9302     }    
9303
9304     /* if more than 1 byte */
9305     else if ( shCount >= 8 ) {
9306         /* lower order three bytes goes to higher order  three bytes */
9307         shCount -= 8;
9308         if(size == 2){
9309             if(shCount)
9310                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9311             else
9312                 movLeft2Result(left, LSB, result, MSB16);
9313         }
9314         else{   /* size = 4 */
9315             if(shCount == 0){
9316                 movLeft2Result(left, MSB24, result, MSB32);
9317                 movLeft2Result(left, MSB16, result, MSB24);
9318                 movLeft2Result(left, LSB, result, MSB16);
9319                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9320             }
9321             else if(shCount == 1)
9322                 shiftLLong(left, result, MSB16);
9323             else{
9324                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9325                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9326                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9327                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9328             }
9329         }
9330     }
9331
9332     /* 1 <= shCount <= 7 */
9333     else if(shCount <= 3)
9334     { 
9335         shiftLLong(left, result, LSB);
9336         while(--shCount >= 1)
9337             shiftLLong(result, result, LSB);
9338     }
9339     /* 3 <= shCount <= 7, optimize */
9340     else{
9341         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9342         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9343         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9344     }
9345 }
9346
9347 /*-----------------------------------------------------------------*/
9348 /* genLeftShiftLiteral - left shifting by known count              */
9349 /*-----------------------------------------------------------------*/
9350 void pic16_genLeftShiftLiteral (operand *left,
9351                                  operand *right,
9352                                  operand *result,
9353                                  iCode *ic)
9354 {    
9355     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9356     int size;
9357
9358     FENTRY;
9359     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9360     pic16_freeAsmop(right,NULL,ic,TRUE);
9361
9362     pic16_aopOp(left,ic,FALSE);
9363     pic16_aopOp(result,ic,TRUE);
9364
9365     size = getSize(operandType(result));
9366
9367 #if VIEW_SIZE
9368     pic16_emitcode("; shift left ","result %d, left %d",size,
9369              AOP_SIZE(left));
9370 #endif
9371
9372     /* I suppose that the left size >= result size */
9373     if(shCount == 0){
9374         while(size--){
9375             movLeft2Result(left, size, result, size);
9376         }
9377     }
9378
9379     else if(shCount >= (size * 8))
9380         while(size--)
9381             pic16_aopPut(AOP(result),zero,size);
9382     else{
9383         switch (size) {
9384             case 1:
9385                 genlshOne (result,left,shCount);
9386                 break;
9387
9388             case 2:
9389             case 3:
9390                 genlshTwo (result,left,shCount);
9391                 break;
9392
9393             case 4:
9394                 genlshFour (result,left,shCount);
9395                 break;
9396         }
9397     }
9398     pic16_freeAsmop(left,NULL,ic,TRUE);
9399     pic16_freeAsmop(result,NULL,ic,TRUE);
9400 }
9401
9402 /*-----------------------------------------------------------------*
9403  * genMultiAsm - repeat assembly instruction for size of register.
9404  * if endian == 1, then the high byte (i.e base address + size of 
9405  * register) is used first else the low byte is used first;
9406  *-----------------------------------------------------------------*/
9407 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9408 {
9409
9410   int offset = 0;
9411
9412   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9413
9414   if(!reg)
9415     return;
9416
9417   if(!endian) {
9418     endian = 1;
9419   } else {
9420     endian = -1;
9421     offset = size-1;
9422   }
9423
9424   while(size--) {
9425     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9426     offset += endian;
9427   }
9428
9429 }
9430
9431 #if !(USE_GENERIC_SIGNED_SHIFT)
9432 /*-----------------------------------------------------------------*/
9433 /* genLeftShift - generates code for left shifting                 */
9434 /*-----------------------------------------------------------------*/
9435 static void genLeftShift (iCode *ic)
9436 {
9437   operand *left,*right, *result;
9438   int size, offset;
9439 //  char *l;
9440   symbol *tlbl , *tlbl1;
9441   pCodeOp *pctemp;
9442
9443   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9444
9445   right = IC_RIGHT(ic);
9446   left  = IC_LEFT(ic);
9447   result = IC_RESULT(ic);
9448
9449   pic16_aopOp(right,ic,FALSE);
9450
9451   /* if the shift count is known then do it 
9452      as efficiently as possible */
9453   if (AOP_TYPE(right) == AOP_LIT) {
9454     pic16_genLeftShiftLiteral (left,right,result,ic);
9455     return ;
9456   }
9457
9458   /* shift count is unknown then we have to form
9459    * a loop. Get the loop count in WREG : Note: we take
9460    * only the lower order byte since shifting
9461    * more than 32 bits make no sense anyway, ( the
9462    * largest size of an object can be only 32 bits ) */
9463   
9464   pic16_aopOp(left,ic,FALSE);
9465   pic16_aopOp(result,ic,FALSE);
9466
9467   /* now move the left to the result if they are not the
9468    * same, and if size > 1,
9469    * and if right is not same to result (!!!) -- VR */
9470   if (!pic16_sameRegs(AOP(left),AOP(result))
9471       && (AOP_SIZE(result) > 1)) {
9472
9473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9474
9475     size = AOP_SIZE(result);
9476     offset=0;
9477     while (size--) {
9478
9479 #if 0
9480       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9481       if (*l == '@' && (IS_AOP_PREG(result))) {
9482
9483           pic16_emitcode("mov","a,%s",l);
9484           pic16_aopPut(AOP(result),"a",offset);
9485       } else
9486 #endif
9487       {
9488         /* we don't know if left is a literal or a register, take care -- VR */
9489         pic16_mov2f(AOP(result), AOP(left), offset);
9490       }
9491       offset++;
9492     }
9493   }
9494
9495   size = AOP_SIZE(result);
9496
9497   /* if it is only one byte then */
9498   if (size == 1) {
9499     if(optimized_for_speed) {
9500       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9501       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9502       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9503       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9504       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9505       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9506       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9507       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9508       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9509       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9510       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9511       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9512     } else {
9513
9514       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9515
9516       tlbl = newiTempLabel(NULL);
9517
9518 #if 1
9519       /* this is already done, why change it? */
9520       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9521                 pic16_mov2f(AOP(result), AOP(left), 0);
9522       }
9523 #endif
9524
9525       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9526       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9527       pic16_emitpLabel(tlbl->key);
9528       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9529       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9530       emitSKPC;
9531       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9532     }
9533     goto release ;
9534   }
9535     
9536   if (pic16_sameRegs(AOP(left),AOP(result))) {
9537
9538     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9539     
9540     tlbl = newiTempLabel(NULL);
9541     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9542     genMultiAsm(POC_RRCF, result, size,1);
9543     pic16_emitpLabel(tlbl->key);
9544     genMultiAsm(POC_RLCF, result, size,0);
9545     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9546     emitSKPC;
9547     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9548     goto release;
9549   }
9550
9551   //tlbl = newiTempLabel(NULL);
9552   //offset = 0 ;   
9553   //tlbl1 = newiTempLabel(NULL);
9554
9555   //reAdjustPreg(AOP(result));    
9556     
9557   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9558   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9559   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9560   //MOVA(l);
9561   //pic16_emitcode("add","a,acc");         
9562   //pic16_aopPut(AOP(result),"a",offset++);
9563   //while (--size) {
9564   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9565   //  MOVA(l);
9566   //  pic16_emitcode("rlc","a");         
9567   //  pic16_aopPut(AOP(result),"a",offset++);
9568   //}
9569   //reAdjustPreg(AOP(result));
9570
9571   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9572   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9573
9574
9575   tlbl = newiTempLabel(NULL);
9576   tlbl1= newiTempLabel(NULL);
9577
9578   size = AOP_SIZE(result);
9579   offset = 1;
9580
9581   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9582
9583   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9584
9585   /* offset should be 0, 1 or 3 */
9586   
9587   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9588   emitSKPNZ;
9589   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9590
9591   pic16_emitpcode(POC_MOVWF, pctemp);
9592
9593
9594   pic16_emitpLabel(tlbl->key);
9595
9596   emitCLRC;
9597   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9598   while(--size)
9599     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9600
9601   pic16_emitpcode(POC_DECFSZ,  pctemp);
9602   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9603   pic16_emitpLabel(tlbl1->key);
9604
9605   pic16_popReleaseTempReg(pctemp,1);
9606
9607
9608  release:
9609   pic16_freeAsmop (right,NULL,ic,TRUE);
9610   pic16_freeAsmop(left,NULL,ic,TRUE);
9611   pic16_freeAsmop(result,NULL,ic,TRUE);
9612 }
9613 #endif
9614
9615
9616 #if 0
9617 #error old code (left here for reference)
9618 /*-----------------------------------------------------------------*/
9619 /* genLeftShift - generates code for left shifting                 */
9620 /*-----------------------------------------------------------------*/
9621 static void genLeftShift (iCode *ic)
9622 {
9623   operand *left,*right, *result;
9624   int size, offset;
9625   char *l;
9626   symbol *tlbl , *tlbl1;
9627   pCodeOp *pctemp;
9628
9629   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9630
9631   right = IC_RIGHT(ic);
9632   left  = IC_LEFT(ic);
9633   result = IC_RESULT(ic);
9634
9635   pic16_aopOp(right,ic,FALSE);
9636
9637   /* if the shift count is known then do it 
9638      as efficiently as possible */
9639   if (AOP_TYPE(right) == AOP_LIT) {
9640     pic16_genLeftShiftLiteral (left,right,result,ic);
9641     return ;
9642   }
9643
9644   /* shift count is unknown then we have to form 
9645      a loop get the loop count in B : Note: we take
9646      only the lower order byte since shifting
9647      more that 32 bits make no sense anyway, ( the
9648      largest size of an object can be only 32 bits ) */  
9649
9650     
9651   pic16_aopOp(left,ic,FALSE);
9652   pic16_aopOp(result,ic,FALSE);
9653
9654   /* now move the left to the result if they are not the
9655      same */
9656   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9657       AOP_SIZE(result) > 1) {
9658
9659     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9660
9661     size = AOP_SIZE(result);
9662     offset=0;
9663     while (size--) {
9664       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9665       if (*l == '@' && (IS_AOP_PREG(result))) {
9666
9667         pic16_emitcode("mov","a,%s",l);
9668         pic16_aopPut(AOP(result),"a",offset);
9669       } else {
9670
9671         /* we don't know if left is a literal or a register, take care -- VR */
9672         pic16_mov2f(AOP(result), AOP(left), offset);
9673       }
9674       offset++;
9675     }
9676   }
9677
9678   size = AOP_SIZE(result);
9679
9680   /* if it is only one byte then */
9681   if (size == 1) {
9682     if(optimized_for_speed) {
9683       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9684       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9685       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9686       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9687       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9688       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9689       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9690       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9691       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9692       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9693       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9694       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9695     } else {
9696
9697       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9698
9699       tlbl = newiTempLabel(NULL);
9700       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9701                 pic16_mov2f(AOP(result), AOP(left), 0);
9702                 
9703 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9704 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9705       }
9706
9707       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9708       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9709       pic16_emitpLabel(tlbl->key);
9710       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9711       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9712       emitSKPC;
9713       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9714     }
9715     goto release ;
9716   }
9717     
9718   if (pic16_sameRegs(AOP(left),AOP(result))) {
9719
9720     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9721     
9722     tlbl = newiTempLabel(NULL);
9723     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9724     genMultiAsm(POC_RRCF, result, size,1);
9725     pic16_emitpLabel(tlbl->key);
9726     genMultiAsm(POC_RLCF, result, size,0);
9727     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9728     emitSKPC;
9729     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9730     goto release;
9731   }
9732
9733   //tlbl = newiTempLabel(NULL);
9734   //offset = 0 ;   
9735   //tlbl1 = newiTempLabel(NULL);
9736
9737   //reAdjustPreg(AOP(result));    
9738     
9739   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9740   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9741   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9742   //MOVA(l);
9743   //pic16_emitcode("add","a,acc");         
9744   //pic16_aopPut(AOP(result),"a",offset++);
9745   //while (--size) {
9746   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9747   //  MOVA(l);
9748   //  pic16_emitcode("rlc","a");         
9749   //  pic16_aopPut(AOP(result),"a",offset++);
9750   //}
9751   //reAdjustPreg(AOP(result));
9752
9753   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9754   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9755
9756
9757   tlbl = newiTempLabel(NULL);
9758   tlbl1= newiTempLabel(NULL);
9759
9760   size = AOP_SIZE(result);
9761   offset = 1;
9762
9763   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9764
9765   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9766
9767   /* offset should be 0, 1 or 3 */
9768   
9769   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9770   emitSKPNZ;
9771   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9772
9773   pic16_emitpcode(POC_MOVWF, pctemp);
9774
9775
9776   pic16_emitpLabel(tlbl->key);
9777
9778   emitCLRC;
9779   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9780   while(--size)
9781     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9782
9783   pic16_emitpcode(POC_DECFSZ,  pctemp);
9784   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9785   pic16_emitpLabel(tlbl1->key);
9786
9787   pic16_popReleaseTempReg(pctemp,1);
9788
9789
9790  release:
9791   pic16_freeAsmop (right,NULL,ic,TRUE);
9792   pic16_freeAsmop(left,NULL,ic,TRUE);
9793   pic16_freeAsmop(result,NULL,ic,TRUE);
9794 }
9795 #endif
9796
9797 /*-----------------------------------------------------------------*/
9798 /* genrshOne - right shift a one byte quantity by known count      */
9799 /*-----------------------------------------------------------------*/
9800 static void genrshOne (operand *result, operand *left,
9801                        int shCount, int sign)
9802 {
9803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9804     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9805 }
9806
9807 /*-----------------------------------------------------------------*/
9808 /* genrshTwo - right shift two bytes by known amount != 0          */
9809 /*-----------------------------------------------------------------*/
9810 static void genrshTwo (operand *result,operand *left,
9811                        int shCount, int sign)
9812 {
9813   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9814   /* if shCount >= 8 */
9815   if (shCount >= 8) {
9816     shCount -= 8 ;
9817     if (shCount)
9818       shiftR1Left2Result(left, MSB16, result, LSB,
9819                          shCount, sign);
9820     else
9821       movLeft2Result(left, MSB16, result, LSB);
9822
9823     pic16_addSign (result, 1, sign);
9824   }
9825
9826   /*  1 <= shCount <= 7 */
9827   else
9828     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9829 }
9830
9831 /*-----------------------------------------------------------------*/
9832 /* shiftRLong - shift right one long from left to result           */
9833 /* offl = LSB or MSB16                                             */
9834 /*-----------------------------------------------------------------*/
9835 static void shiftRLong (operand *left, int offl,
9836                         operand *result, int sign)
9837 {
9838     int size = AOP_SIZE(result);
9839     int same = pic16_sameRegs(AOP(left),AOP(result));
9840     int i;
9841     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9842
9843         if (same && (offl == MSB16)) { //shift one byte right
9844                 for(i=MSB16;i<size;i++) {
9845                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9846                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9847                 }
9848         }
9849
9850     if(sign)
9851                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9852         else
9853                 emitCLRC;
9854
9855         if (same) {
9856                 if (offl == LSB)
9857                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9858         } else {
9859         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9860         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9861         }
9862
9863     if(offl == MSB16) {
9864         /* add sign of "a" */
9865         pic16_addSign(result, MSB32, sign);
9866         }
9867
9868         if (same) {
9869         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9870         } else {
9871         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9872         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9873         }
9874         
9875         if (same) {
9876         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9877         } else {
9878         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9879         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9880         }
9881
9882         if (same) {
9883         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9884         } else {
9885         if(offl == LSB){
9886                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9887                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9888         }
9889         }
9890 }
9891
9892 /*-----------------------------------------------------------------*/
9893 /* genrshFour - shift four byte by a known amount != 0             */
9894 /*-----------------------------------------------------------------*/
9895 static void genrshFour (operand *result, operand *left,
9896                         int shCount, int sign)
9897 {
9898   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9899   /* if shifting more that 3 bytes */
9900   if(shCount >= 24 ) {
9901     shCount -= 24;
9902     if(shCount)
9903       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9904     else
9905       movLeft2Result(left, MSB32, result, LSB);
9906
9907     pic16_addSign(result, MSB16, sign);
9908   }
9909   else if(shCount >= 16){
9910     shCount -= 16;
9911     if(shCount)
9912       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9913     else{
9914       movLeft2Result(left, MSB24, result, LSB);
9915       movLeft2Result(left, MSB32, result, MSB16);
9916     }
9917     pic16_addSign(result, MSB24, sign);
9918   }
9919   else if(shCount >= 8){
9920     shCount -= 8;
9921     if(shCount == 1)
9922       shiftRLong(left, MSB16, result, sign);
9923     else if(shCount == 0){
9924       movLeft2Result(left, MSB16, result, LSB);
9925       movLeft2Result(left, MSB24, result, MSB16);
9926       movLeft2Result(left, MSB32, result, MSB24);
9927       pic16_addSign(result, MSB32, sign);
9928     }
9929     else{ //shcount >= 2
9930       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9931       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9932       /* the last shift is signed */
9933       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9934       pic16_addSign(result, MSB32, sign);
9935     }
9936   }
9937   else{   /* 1 <= shCount <= 7 */
9938     if(shCount <= 2){
9939       shiftRLong(left, LSB, result, sign);
9940       if(shCount == 2)
9941         shiftRLong(result, LSB, result, sign);
9942     }
9943     else{
9944       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9945       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9946       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9947     }
9948   }
9949 }
9950
9951 /*-----------------------------------------------------------------*/
9952 /* genRightShiftLiteral - right shifting by known count            */
9953 /*-----------------------------------------------------------------*/
9954 static void genRightShiftLiteral (operand *left,
9955                                   operand *right,
9956                                   operand *result,
9957                                   iCode *ic,
9958                                   int sign)
9959 {    
9960   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9961   int lsize,res_size;
9962
9963   pic16_freeAsmop(right,NULL,ic,TRUE);
9964
9965   pic16_aopOp(left,ic,FALSE);
9966   pic16_aopOp(result,ic,TRUE);
9967
9968   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9969
9970 #if VIEW_SIZE
9971   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9972                  AOP_SIZE(left));
9973 #endif
9974
9975   lsize = pic16_getDataSize(left);
9976   res_size = pic16_getDataSize(result);
9977   /* test the LEFT size !!! */
9978
9979   /* I suppose that the left size >= result size */
9980   if(shCount == 0){
9981     assert (res_size <= lsize);
9982     while (res_size--) {
9983       pic16_mov2f (AOP(result), AOP(left), res_size);
9984     } // for
9985   }
9986
9987   else if(shCount >= (lsize * 8)){
9988
9989     if(res_size == 1) {
9990       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9991       if(sign) {
9992         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9993         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9994       }
9995     } else {
9996
9997       if(sign) {
9998         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9999         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10000         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10001         while(res_size--)
10002           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10003
10004       } else {
10005
10006         while(res_size--)
10007           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10008       }
10009     }
10010   } else {
10011
10012     switch (res_size) {
10013     case 1:
10014       genrshOne (result,left,shCount,sign);
10015       break;
10016
10017     case 2:
10018       genrshTwo (result,left,shCount,sign);
10019       break;
10020
10021     case 4:
10022       genrshFour (result,left,shCount,sign);
10023       break;
10024     default :
10025       break;
10026     }
10027
10028   }
10029
10030   pic16_freeAsmop(left,NULL,ic,TRUE);
10031   pic16_freeAsmop(result,NULL,ic,TRUE);
10032 }
10033
10034 #if !(USE_GENERIC_SIGNED_SHIFT)
10035 /*-----------------------------------------------------------------*/
10036 /* genSignedRightShift - right shift of signed number              */
10037 /*-----------------------------------------------------------------*/
10038 static void genSignedRightShift (iCode *ic)
10039 {
10040   operand *right, *left, *result;
10041   int size, offset;
10042   //  char *l;
10043   symbol *tlbl, *tlbl1 ;
10044   pCodeOp *pctemp;
10045
10046   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10047
10048   /* we do it the hard way put the shift count in b
10049      and loop thru preserving the sign */
10050   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10051
10052   right = IC_RIGHT(ic);
10053   left  = IC_LEFT(ic);
10054   result = IC_RESULT(ic);
10055
10056   pic16_aopOp(right,ic,FALSE);  
10057   pic16_aopOp(left,ic,FALSE);
10058   pic16_aopOp(result,ic,FALSE);
10059
10060
10061   if ( AOP_TYPE(right) == AOP_LIT) {
10062     genRightShiftLiteral (left,right,result,ic,1);
10063     return ;
10064   }
10065   /* shift count is unknown then we have to form 
10066      a loop get the loop count in B : Note: we take
10067      only the lower order byte since shifting
10068      more that 32 bits make no sense anyway, ( the
10069      largest size of an object can be only 32 bits ) */  
10070
10071   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10072   //pic16_emitcode("inc","b");
10073   //pic16_freeAsmop (right,NULL,ic,TRUE);
10074   //pic16_aopOp(left,ic,FALSE);
10075   //pic16_aopOp(result,ic,FALSE);
10076
10077   /* now move the left to the result if they are not the
10078      same */
10079   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10080       AOP_SIZE(result) > 1) {
10081
10082     size = AOP_SIZE(result);
10083     offset=0;
10084     while (size--) { 
10085       /*
10086         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10087         if (*l == '@' && IS_AOP_PREG(result)) {
10088
10089         pic16_emitcode("mov","a,%s",l);
10090         pic16_aopPut(AOP(result),"a",offset);
10091         } else
10092         pic16_aopPut(AOP(result),l,offset);
10093       */
10094       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10095       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10096
10097       offset++;
10098     }
10099   }
10100
10101   /* mov the highest order bit to OVR */    
10102   tlbl = newiTempLabel(NULL);
10103   tlbl1= newiTempLabel(NULL);
10104
10105   size = AOP_SIZE(result);
10106   offset = size - 1;
10107
10108   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10109
10110   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10111
10112   /* offset should be 0, 1 or 3 */
10113   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10114   emitSKPNZ;
10115   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10116
10117   pic16_emitpcode(POC_MOVWF, pctemp);
10118
10119
10120   pic16_emitpLabel(tlbl->key);
10121
10122   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10123   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10124
10125   while(--size) {
10126     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10127   }
10128
10129   pic16_emitpcode(POC_DECFSZ,  pctemp);
10130   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10131   pic16_emitpLabel(tlbl1->key);
10132
10133   pic16_popReleaseTempReg(pctemp,1);
10134 #if 0
10135   size = AOP_SIZE(result);
10136   offset = size - 1;
10137   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10138   pic16_emitcode("rlc","a");
10139   pic16_emitcode("mov","ov,c");
10140   /* if it is only one byte then */
10141   if (size == 1) {
10142     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10143     MOVA(l);
10144     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10145     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10146     pic16_emitcode("mov","c,ov");
10147     pic16_emitcode("rrc","a");
10148     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10149     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10150     pic16_aopPut(AOP(result),"a",0);
10151     goto release ;
10152   }
10153
10154   reAdjustPreg(AOP(result));
10155   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10156   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10157   pic16_emitcode("mov","c,ov");
10158   while (size--) {
10159     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10160     MOVA(l);
10161     pic16_emitcode("rrc","a");         
10162     pic16_aopPut(AOP(result),"a",offset--);
10163   }
10164   reAdjustPreg(AOP(result));
10165   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10166   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10167
10168  release:
10169 #endif
10170
10171   pic16_freeAsmop(left,NULL,ic,TRUE);
10172   pic16_freeAsmop(result,NULL,ic,TRUE);
10173   pic16_freeAsmop(right,NULL,ic,TRUE);
10174 }
10175 #endif
10176
10177 #if !(USE_GENERIC_SIGNED_SHIFT)
10178 #warning This implementation of genRightShift() is incomplete!
10179 /*-----------------------------------------------------------------*/
10180 /* genRightShift - generate code for right shifting                */
10181 /*-----------------------------------------------------------------*/
10182 static void genRightShift (iCode *ic)
10183 {
10184     operand *right, *left, *result;
10185     sym_link *letype ;
10186     int size, offset;
10187     char *l;
10188     symbol *tlbl, *tlbl1 ;
10189
10190     /* if signed then we do it the hard way preserve the
10191     sign bit moving it inwards */
10192     letype = getSpec(operandType(IC_LEFT(ic)));
10193     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10194
10195     if (!SPEC_USIGN(letype)) {
10196         genSignedRightShift (ic);
10197         return ;
10198     }
10199
10200     /* signed & unsigned types are treated the same : i.e. the
10201     signed is NOT propagated inwards : quoting from the
10202     ANSI - standard : "for E1 >> E2, is equivalent to division
10203     by 2**E2 if unsigned or if it has a non-negative value,
10204     otherwise the result is implementation defined ", MY definition
10205     is that the sign does not get propagated */
10206
10207     right = IC_RIGHT(ic);
10208     left  = IC_LEFT(ic);
10209     result = IC_RESULT(ic);
10210
10211     pic16_aopOp(right,ic,FALSE);
10212
10213     /* if the shift count is known then do it 
10214     as efficiently as possible */
10215     if (AOP_TYPE(right) == AOP_LIT) {
10216         genRightShiftLiteral (left,right,result,ic, 0);
10217         return ;
10218     }
10219
10220     /* shift count is unknown then we have to form 
10221     a loop get the loop count in B : Note: we take
10222     only the lower order byte since shifting
10223     more that 32 bits make no sense anyway, ( the
10224     largest size of an object can be only 32 bits ) */  
10225
10226     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10227     pic16_emitcode("inc","b");
10228     pic16_aopOp(left,ic,FALSE);
10229     pic16_aopOp(result,ic,FALSE);
10230
10231     /* now move the left to the result if they are not the
10232     same */
10233     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10234         AOP_SIZE(result) > 1) {
10235
10236         size = AOP_SIZE(result);
10237         offset=0;
10238         while (size--) {
10239             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10240             if (*l == '@' && IS_AOP_PREG(result)) {
10241
10242                 pic16_emitcode("mov","a,%s",l);
10243                 pic16_aopPut(AOP(result),"a",offset);
10244             } else
10245                 pic16_aopPut(AOP(result),l,offset);
10246             offset++;
10247         }
10248     }
10249
10250     tlbl = newiTempLabel(NULL);
10251     tlbl1= newiTempLabel(NULL);
10252     size = AOP_SIZE(result);
10253     offset = size - 1;
10254
10255     /* if it is only one byte then */
10256     if (size == 1) {
10257
10258       tlbl = newiTempLabel(NULL);
10259       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10260         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10261         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10262       }
10263
10264       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10265       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10266       pic16_emitpLabel(tlbl->key);
10267       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10268       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10269       emitSKPC;
10270       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10271
10272       goto release ;
10273     }
10274
10275     reAdjustPreg(AOP(result));
10276     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10277     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10278     CLRC;
10279     while (size--) {
10280         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10281         MOVA(l);
10282         pic16_emitcode("rrc","a");         
10283         pic16_aopPut(AOP(result),"a",offset--);
10284     }
10285     reAdjustPreg(AOP(result));
10286
10287     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10288     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10289
10290 release:
10291     pic16_freeAsmop(left,NULL,ic,TRUE);
10292     pic16_freeAsmop (right,NULL,ic,TRUE);
10293     pic16_freeAsmop(result,NULL,ic,TRUE);
10294 }
10295 #endif
10296
10297 #if (USE_GENERIC_SIGNED_SHIFT)
10298 /*-----------------------------------------------------------------*/
10299 /* genGenericShift - generates code for left or right shifting     */
10300 /*-----------------------------------------------------------------*/
10301 static void genGenericShift (iCode *ic, int isShiftLeft) {
10302   operand *left,*right, *result;
10303   int offset;
10304   int sign, signedCount;
10305   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10306   PIC_OPCODE pos_shift, neg_shift;
10307
10308   FENTRY;
10309
10310   right = IC_RIGHT(ic);
10311   left  = IC_LEFT(ic);
10312   result = IC_RESULT(ic);
10313
10314   pic16_aopOp(right,ic,FALSE);
10315   pic16_aopOp(left,ic,FALSE);
10316   pic16_aopOp(result,ic,TRUE);
10317
10318   sign = !SPEC_USIGN(operandType (left));
10319   signedCount = !SPEC_USIGN(operandType (right));
10320
10321   /* if the shift count is known then do it 
10322      as efficiently as possible */
10323   if (AOP_TYPE(right) == AOP_LIT) {
10324     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10325     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10326     // we should modify right->aopu.aop_lit here!
10327     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10328     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10329     if (isShiftLeft)
10330       pic16_genLeftShiftLiteral (left,right,result,ic);
10331     else
10332       genRightShiftLiteral (left,right,result,ic, sign);
10333
10334     goto release;
10335   } // if (right is literal)
10336
10337   /* shift count is unknown then we have to form a loop.
10338    * Note: we take only the lower order byte since shifting
10339    * more than 32 bits make no sense anyway, ( the
10340    * largest size of an object can be only 32 bits )
10341    * Note: we perform arithmetic shifts if the left operand is
10342    * signed and we do an (effective) right shift, i. e. we
10343    * shift in the sign bit from the left. */
10344    
10345   label_complete = newiTempLabel ( NULL );
10346   label_loop_pos = newiTempLabel ( NULL );
10347   label_loop_neg = NULL;
10348   label_negative = NULL;
10349   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10350   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10351
10352   if (signedCount) {
10353     // additional labels needed
10354     label_loop_neg = newiTempLabel ( NULL );
10355     label_negative = newiTempLabel ( NULL );
10356   } // if
10357
10358   // copy source to result -- this will effectively truncate the left operand to the size of result!
10359   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10360   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10361   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10362     pic16_mov2f (AOP(result),AOP(left), offset);
10363   } // for
10364
10365   // if result is longer than left, fill with zeros (or sign)
10366   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10367     if (sign && AOP_SIZE(left) > 0) {
10368       // shift signed operand -- fill with sign
10369       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10370       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10371       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10372       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10373         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10374       } // for
10375     } else {
10376       // shift unsigned operand -- fill result with zeros
10377       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10378         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10379       } // for
10380     }
10381   } // if (size mismatch)
10382
10383   pic16_mov2w (AOP(right), 0);
10384   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10385   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10386   
10387 #if 0
10388   // perform a shift by one (shift count is positive)
10389   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10390   // 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])
10391   pic16_emitpLabel (label_loop_pos->key);
10392   emitCLRC;
10393   if (sign && (pos_shift == POC_RRCF)) {
10394     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10395     emitSETC;
10396   } // if
10397   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10398   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10399   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10400 #else
10401   // perform a shift by one (shift count is positive)
10402   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10403   // 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])
10404   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10405   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10406   emitCLRC;
10407   pic16_emitpLabel (label_loop_pos->key);
10408   if (sign && (pos_shift == POC_RRCF)) {
10409     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10410     emitSETC;
10411   } // if
10412   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10413   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10414   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10415   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10416 #endif
10417
10418   if (signedCount) {
10419     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10420
10421     pic16_emitpLabel (label_negative->key);
10422     // perform a shift by -1 (shift count is negative)
10423     // 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)
10424     emitCLRC;
10425     pic16_emitpLabel (label_loop_neg->key);
10426     if (sign && (neg_shift == POC_RRCF)) {
10427       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10428       emitSETC;
10429     } // if
10430     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10431     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10432     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10433     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10434   } // if (signedCount)
10435
10436   pic16_emitpLabel (label_complete->key);
10437
10438 release:
10439   pic16_freeAsmop (right,NULL,ic,TRUE);
10440   pic16_freeAsmop(left,NULL,ic,TRUE);
10441   pic16_freeAsmop(result,NULL,ic,TRUE);
10442 }
10443
10444 static void genLeftShift (iCode *ic) {
10445   genGenericShift (ic, 1);
10446 }
10447
10448 static void genRightShift (iCode *ic) {
10449   genGenericShift (ic, 0);
10450 }
10451 #endif
10452
10453
10454 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10455 void pic16_loadFSR0(operand *op, int lit)
10456 {
10457   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10458     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10459   } else {
10460     assert (!OP_SYMBOL(op)->remat);
10461     // set up FSR0 with address of result
10462     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10463     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10464   }
10465 }
10466
10467 /*----------------------------------------------------------------*/
10468 /* pic16_derefPtr - move one byte from the location ptr points to */
10469 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10470 /*                  to the location ptr points to (doWrite != 0)   */
10471 /*----------------------------------------------------------------*/
10472 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10473 {
10474   if (!IS_PTR(operandType(ptr)))
10475   {
10476     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10477     else pic16_mov2w (AOP(ptr), 0);
10478     return;
10479   }
10480
10481   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10482   /* We might determine pointer type right here: */
10483   p_type = DCL_TYPE(operandType(ptr));
10484
10485   switch (p_type) {
10486     case FPOINTER:
10487     case POINTER:
10488       if (!fsr0_setup || !*fsr0_setup)
10489       {
10490         pic16_loadFSR0( ptr, 0 );
10491         if (fsr0_setup) *fsr0_setup = 1;
10492       }
10493       if (doWrite)
10494         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10495       else
10496         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10497       break;
10498
10499     case GPOINTER:
10500       if (AOP(ptr)->aopu.aop_reg[2]) {
10501         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10502         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10503         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10504         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10505         pic16_mov2w(AOP(ptr), 2);
10506         pic16_callGenericPointerRW(doWrite, 1);
10507       } else {
10508         // data pointer (just 2 byte given)
10509         if (!fsr0_setup || !*fsr0_setup)
10510         {
10511           pic16_loadFSR0( ptr, 0 );
10512           if (fsr0_setup) *fsr0_setup = 1;
10513         }
10514         if (doWrite)
10515           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10516         else
10517           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10518       }
10519       break;
10520
10521     default:
10522       assert (0 && "invalid pointer type specified");
10523       break;
10524   }
10525 }
10526
10527 /*-----------------------------------------------------------------*/
10528 /* genUnpackBits - generates code for unpacking bits               */
10529 /*-----------------------------------------------------------------*/
10530 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10531 {    
10532   int shCnt ;
10533   sym_link *etype, *letype;
10534   int blen=0, bstr=0;
10535   int lbstr;
10536   int same;
10537   pCodeOp *op;
10538
10539   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10540   etype = getSpec(operandType(result));
10541   letype = getSpec(operandType(left));
10542
10543   //    if(IS_BITFIELD(etype)) {
10544   blen = SPEC_BLEN(etype);
10545   bstr = SPEC_BSTR(etype);
10546   //    }
10547
10548   lbstr = SPEC_BSTR( letype );
10549
10550   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10551       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10552
10553 #if 1
10554   if((blen == 1) && (bstr < 8)
10555       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10556     /* it is a single bit, so use the appropriate bit instructions */
10557     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10558
10559     same = pic16_sameRegs(AOP(left),AOP(result));
10560     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10561     pic16_emitpcode(POC_CLRF, op);
10562
10563     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10564       /* workaround to reduce the extra lfsr instruction */
10565       pic16_emitpcode(POC_BTFSC,
10566           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10567     } else {
10568       assert (PIC_IS_DATA_PTR (operandType(left)));
10569       pic16_loadFSR0 (left, 0);
10570       pic16_emitpcode(POC_BTFSC,
10571           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10572     }
10573
10574     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10575       /* unsigned bitfields result in either 0 or 1 */
10576       pic16_emitpcode(POC_INCF, op);
10577     } else {
10578       /* signed bitfields result in either 0 or -1 */
10579       pic16_emitpcode(POC_DECF, op);
10580     }
10581     if (same) {
10582       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10583     }
10584
10585     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10586     return;
10587   }
10588
10589 #endif
10590
10591   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10592     // access symbol directly
10593     pic16_mov2w (AOP(left), 0);
10594   } else {
10595     pic16_derefPtr (left, ptype, 0, NULL);
10596   }
10597
10598   /* if we have bitdisplacement then it fits   */
10599   /* into this byte completely or if length is */
10600   /* less than a byte                          */
10601   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10602
10603     /* shift right acc */
10604     AccRsh(shCnt, 0);
10605
10606     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10607           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10608
10609     /* VR -- normally I would use the following, but since we use the hack,
10610      * to avoid the masking from AccRsh, why not mask it right now? */
10611
10612     /*
10613        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10614      */
10615
10616     /* extend signed bitfields to 8 bits */
10617     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10618     {
10619       assert (blen + bstr > 0);
10620       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10621       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10622     }
10623
10624     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10625
10626     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10627     return ;
10628   }
10629
10630   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10631   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10632   exit(-1);
10633
10634   return ;
10635 }
10636
10637
10638 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10639 {
10640   int size, offset = 0, leoffset=0 ;
10641
10642         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10643         pic16_aopOp(result, ic, TRUE);
10644
10645         FENTRY;
10646
10647         size = AOP_SIZE(result);
10648 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10649
10650
10651 #if 1
10652         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10653                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10654                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10655                 goto release;
10656         }
10657 #endif
10658
10659         if(AOP(left)->aopu.pcop->type == PO_DIR)
10660                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10661
10662         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10663
10664         while (size--) {
10665                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10666                 
10667 //              pic16_DumpOp("(result)",result);
10668                 if(is_LitAOp(AOP(result))) {
10669                         pic16_mov2w(AOP(left), offset); // patch 8
10670                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10671                 } else {
10672                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10673                                 pic16_popGet(AOP(left), offset), //patch 8
10674                                 pic16_popGet(AOP(result), offset)));
10675                 }
10676
10677                 offset++;
10678                 leoffset++;
10679         }
10680
10681 release:
10682     pic16_freeAsmop(result,NULL,ic,TRUE);
10683 }
10684
10685
10686
10687 /*-----------------------------------------------------------------*/
10688 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10689 /*-----------------------------------------------------------------*/
10690 static void genNearPointerGet (operand *left, 
10691                                operand *result, 
10692                                iCode *ic)
10693 {
10694 //  asmop *aop = NULL;
10695   //regs *preg = NULL ;
10696   sym_link *rtype, *retype;
10697   sym_link *ltype, *letype;
10698
10699     FENTRY;
10700     
10701     rtype = operandType(result);
10702     retype= getSpec(rtype);
10703     ltype = operandType(left);
10704     letype= getSpec(ltype);
10705     
10706     pic16_aopOp(left,ic,FALSE);
10707
10708 //    pic16_DumpOp("(left)",left);
10709 //    pic16_DumpOp("(result)",result);
10710
10711     /* if left is rematerialisable and
10712      * result is not bit variable type and
10713      * the left is pointer to data space i.e
10714      * lower 128 bytes of space */
10715     
10716     if (AOP_TYPE(left) == AOP_PCODE
10717       && !IS_BITFIELD(retype)
10718       && DCL_TYPE(ltype) == POINTER) {
10719
10720         genDataPointerGet (left,result,ic);
10721         pic16_freeAsmop(left, NULL, ic, TRUE);
10722         return ;
10723     }
10724     
10725     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10726     pic16_aopOp (result,ic,TRUE);
10727     
10728     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10729
10730 #if 1
10731     if(IS_BITFIELD( retype )
10732       && (SPEC_BLEN(operandType(result))==1)
10733     ) {
10734       iCode *nextic;
10735       pCodeOp *jop;
10736       int bitstrt, bytestrt;
10737
10738         /* if this is bitfield of size 1, see if we are checking the value
10739          * of a single bit in an if-statement,
10740          * if yes, then don't generate usual code, but execute the
10741          * genIfx directly -- VR */
10742
10743         nextic = ic->next;
10744
10745         /* CHECK: if next iCode is IFX
10746          * and current result operand is nextic's conditional operand
10747          * and current result operand live ranges ends at nextic's key number
10748          */
10749         if((nextic->op == IFX)
10750           && (result == IC_COND(nextic))
10751           && (OP_LIVETO(result) == nextic->seq)
10752           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10753           ) {
10754             /* everything is ok then */
10755             /* find a way to optimize the genIfx iCode */
10756
10757             bytestrt = SPEC_BSTR(operandType(result))/8;
10758             bitstrt = SPEC_BSTR(operandType(result))%8;
10759             
10760             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10761
10762             genIfxpCOpJump(nextic, jop);
10763             
10764             pic16_freeAsmop(left, NULL, ic, TRUE);
10765             pic16_freeAsmop(result, NULL, ic, TRUE);
10766             return;
10767         }
10768     }
10769 #endif
10770
10771     /* if bitfield then unpack the bits */
10772     if (IS_BITFIELD(letype)) 
10773       genUnpackBits (result, left, NULL, POINTER);
10774     else {
10775       /* we have can just get the values */
10776       int size = AOP_SIZE(result);
10777       int offset = 0;   
10778         
10779       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10780
10781       pic16_loadFSR0( left, 0 );
10782
10783       while(size--) {
10784         if(size) {
10785           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10786                 pic16_popGet(AOP(result), offset++)));
10787         } else {
10788           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10789                 pic16_popGet(AOP(result), offset++)));
10790         }
10791       }
10792     }
10793
10794 #if 0
10795     /* now some housekeeping stuff */
10796     if (aop) {
10797       /* we had to allocate for this iCode */
10798       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10799       pic16_freeAsmop(NULL,aop,ic,TRUE);
10800     } else { 
10801       /* we did not allocate which means left
10802        * already in a pointer register, then
10803        * if size > 0 && this could be used again
10804        * we have to point it back to where it 
10805        * belongs */
10806       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10807       if (AOP_SIZE(result) > 1
10808         && !OP_SYMBOL(left)->remat
10809         && ( OP_SYMBOL(left)->liveTo > ic->seq
10810             || ic->depth )) {
10811 //        int size = AOP_SIZE(result) - 1;
10812 //        while (size--)
10813 //          pic16_emitcode("dec","%s",rname);
10814         }
10815     }
10816 #endif
10817
10818     /* done */
10819     pic16_freeAsmop(left,NULL,ic,TRUE);
10820     pic16_freeAsmop(result,NULL,ic,TRUE);
10821 }
10822
10823 /*-----------------------------------------------------------------*/
10824 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10825 /*-----------------------------------------------------------------*/
10826 static void genPagedPointerGet (operand *left, 
10827                                operand *result, 
10828                                iCode *ic)
10829 {
10830     asmop *aop = NULL;
10831     regs *preg = NULL ;
10832     char *rname ;
10833     sym_link *rtype, *retype;    
10834
10835     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10836
10837     rtype = operandType(result);
10838     retype= getSpec(rtype);
10839     
10840     pic16_aopOp(left,ic,FALSE);
10841
10842   /* if the value is already in a pointer register
10843        then don't need anything more */
10844     if (!AOP_INPREG(AOP(left))) {
10845         /* otherwise get a free pointer register */
10846         aop = newAsmop(0);
10847         preg = getFreePtr(ic,&aop,FALSE);
10848         pic16_emitcode("mov","%s,%s",
10849                 preg->name,
10850                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10851         rname = preg->name ;
10852     } else
10853         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10854     
10855     pic16_freeAsmop(left,NULL,ic,TRUE);
10856     pic16_aopOp (result,ic,TRUE);
10857
10858     /* if bitfield then unpack the bits */
10859     if (IS_BITFIELD(retype)) 
10860         genUnpackBits (result,left,rname,PPOINTER);
10861     else {
10862         /* we have can just get the values */
10863         int size = AOP_SIZE(result);
10864         int offset = 0 ;        
10865         
10866         while (size--) {
10867             
10868             pic16_emitcode("movx","a,@%s",rname);
10869             pic16_aopPut(AOP(result),"a",offset);
10870             
10871             offset++ ;
10872             
10873             if (size)
10874                 pic16_emitcode("inc","%s",rname);
10875         }
10876     }
10877
10878     /* now some housekeeping stuff */
10879     if (aop) {
10880         /* we had to allocate for this iCode */
10881         pic16_freeAsmop(NULL,aop,ic,TRUE);
10882     } else { 
10883         /* we did not allocate which means left
10884            already in a pointer register, then
10885            if size > 0 && this could be used again
10886            we have to point it back to where it 
10887            belongs */
10888         if (AOP_SIZE(result) > 1 &&
10889             !OP_SYMBOL(left)->remat &&
10890             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10891               ic->depth )) {
10892             int size = AOP_SIZE(result) - 1;
10893             while (size--)
10894                 pic16_emitcode("dec","%s",rname);
10895         }
10896     }
10897
10898     /* done */
10899     pic16_freeAsmop(result,NULL,ic,TRUE);
10900     
10901         
10902 }
10903
10904 #if 0
10905 /* This code is not adjusted to PIC16 and fails utterly.
10906  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10907
10908 /*-----------------------------------------------------------------*/
10909 /* genFarPointerGet - gget value from far space                    */
10910 /*-----------------------------------------------------------------*/
10911 static void genFarPointerGet (operand *left,
10912                               operand *result, iCode *ic)
10913 {
10914     int size, offset ;
10915     sym_link *retype = getSpec(operandType(result));
10916
10917     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10918
10919     pic16_aopOp(left,ic,FALSE);
10920
10921     /* if the operand is already in dptr 
10922     then we do nothing else we move the value to dptr */
10923     if (AOP_TYPE(left) != AOP_STR) {
10924         /* if this is remateriazable */
10925         if (AOP_TYPE(left) == AOP_IMMD)
10926             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10927         else { /* we need to get it byte by byte */
10928             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10929             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10930             if (options.model == MODEL_FLAT24)
10931             {
10932                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10933             }
10934         }
10935     }
10936     /* so dptr know contains the address */
10937     pic16_freeAsmop(left,NULL,ic,TRUE);
10938     pic16_aopOp(result,ic,TRUE);
10939
10940     /* if bit then unpack */
10941     if (IS_BITFIELD(retype)) 
10942         genUnpackBits(result,left,"dptr",FPOINTER);
10943     else {
10944         size = AOP_SIZE(result);
10945         offset = 0 ;
10946
10947         while (size--) {
10948             pic16_emitcode("movx","a,@dptr");
10949             pic16_aopPut(AOP(result),"a",offset++);
10950             if (size)
10951                 pic16_emitcode("inc","dptr");
10952         }
10953     }
10954
10955     pic16_freeAsmop(result,NULL,ic,TRUE);
10956 }
10957 #endif
10958
10959 #if 0
10960 /*-----------------------------------------------------------------*/
10961 /* genCodePointerGet - get value from code space                  */
10962 /*-----------------------------------------------------------------*/
10963 static void genCodePointerGet (operand *left,
10964                                 operand *result, iCode *ic)
10965 {
10966     int size, offset ;
10967     sym_link *retype = getSpec(operandType(result));
10968
10969     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10970
10971     pic16_aopOp(left,ic,FALSE);
10972
10973     /* if the operand is already in dptr 
10974     then we do nothing else we move the value to dptr */
10975     if (AOP_TYPE(left) != AOP_STR) {
10976         /* if this is remateriazable */
10977         if (AOP_TYPE(left) == AOP_IMMD)
10978             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10979         else { /* we need to get it byte by byte */
10980             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10981             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10982             if (options.model == MODEL_FLAT24)
10983             {
10984                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10985             }
10986         }
10987     }
10988     /* so dptr know contains the address */
10989     pic16_freeAsmop(left,NULL,ic,TRUE);
10990     pic16_aopOp(result,ic,FALSE);
10991
10992     /* if bit then unpack */
10993     if (IS_BITFIELD(retype)) 
10994         genUnpackBits(result,left,"dptr",CPOINTER);
10995     else {
10996         size = AOP_SIZE(result);
10997         offset = 0 ;
10998
10999         while (size--) {
11000             pic16_emitcode("clr","a");
11001             pic16_emitcode("movc","a,@a+dptr");
11002             pic16_aopPut(AOP(result),"a",offset++);
11003             if (size)
11004                 pic16_emitcode("inc","dptr");
11005         }
11006     }
11007
11008     pic16_freeAsmop(result,NULL,ic,TRUE);
11009 }
11010 #endif
11011
11012 #if 0
11013 /*-----------------------------------------------------------------*/
11014 /* genGenPointerGet - gget value from generic pointer space        */
11015 /*-----------------------------------------------------------------*/
11016 static void genGenPointerGet (operand *left,
11017                               operand *result, iCode *ic)
11018 {
11019   int size, offset, lit;
11020   sym_link *retype = getSpec(operandType(result));
11021
11022         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11023         pic16_aopOp(left,ic,FALSE);
11024         pic16_aopOp(result,ic,FALSE);
11025         size = AOP_SIZE(result);
11026
11027         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11028
11029         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11030
11031                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11032                 // load FSR0 from immediate
11033                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11034
11035 //              pic16_loadFSR0( left );
11036
11037                 offset = 0;
11038                 while(size--) {
11039                         if(size) {
11040                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11041                         } else {
11042                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11043                         }
11044                         offset++;
11045                 }
11046                 goto release;
11047
11048         }
11049         else { /* we need to get it byte by byte */
11050                 // set up FSR0 with address from left
11051                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11052                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11053                 
11054                 offset = 0 ;
11055
11056                 while(size--) {
11057                         if(size) {
11058                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11059                         } else {
11060                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11061                         }
11062                         offset++;
11063                 }
11064                 goto release;
11065         }
11066
11067   /* if bit then unpack */
11068         if (IS_BITFIELD(retype)) 
11069                 genUnpackBits(result,left,"BAD",GPOINTER);
11070
11071         release:
11072         pic16_freeAsmop(left,NULL,ic,TRUE);
11073         pic16_freeAsmop(result,NULL,ic,TRUE);
11074
11075 }
11076 #endif
11077
11078
11079 /*-----------------------------------------------------------------*/
11080 /* genGenPointerGet - gget value from generic pointer space        */
11081 /*-----------------------------------------------------------------*/
11082 static void genGenPointerGet (operand *left,
11083                               operand *result, iCode *ic)
11084 {
11085   int size, offset, lit;
11086   sym_link *letype = getSpec(operandType(left));
11087
11088     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11089     pic16_aopOp(left,ic,FALSE);
11090     pic16_aopOp(result,ic,TRUE);
11091     size = AOP_SIZE(result);
11092
11093     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11094   
11095     /* if bit then unpack */
11096     if (IS_BITFIELD(letype)) {
11097       genUnpackBits(result,left,"BAD",GPOINTER);
11098       goto release;
11099     }
11100
11101     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11102
11103       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11104       // load FSR0 from immediate
11105       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11106
11107       werror(W_POSSBUG2, __FILE__, __LINE__);
11108
11109       offset = 0;
11110       while(size--) {
11111         if(size) {
11112           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11113         } else {
11114           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11115         }
11116         offset++;
11117       }
11118
11119       goto release;
11120
11121     } else { /* we need to get it byte by byte */
11122
11123       /* set up WREG:PRODL:FSR0L with address from left */
11124       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11125       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11126       pic16_mov2w(AOP(left), 2);
11127       pic16_callGenericPointerRW(0, size);
11128       
11129       assignResultValue(result, 1);
11130       
11131       goto release;
11132     }
11133
11134 release:
11135   pic16_freeAsmop(left,NULL,ic,TRUE);
11136   pic16_freeAsmop(result,NULL,ic,TRUE);
11137 }
11138
11139 /*-----------------------------------------------------------------*/
11140 /* genConstPointerGet - get value from const generic pointer space */
11141 /*-----------------------------------------------------------------*/
11142 static void genConstPointerGet (operand *left,
11143                                 operand *result, iCode *ic)
11144 {
11145   //sym_link *retype = getSpec(operandType(result));
11146   // symbol *albl = newiTempLabel(NULL);        // patch 15
11147   // symbol *blbl = newiTempLabel(NULL);        //
11148   // PIC_OPCODE poc;                            // patch 15
11149   int size;
11150   int offset = 0;
11151
11152   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11153   pic16_aopOp(left,ic,FALSE);
11154   pic16_aopOp(result,ic,TRUE);
11155   size = AOP_SIZE(result);
11156
11157   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11158
11159   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11160
11161   // set up table pointer
11162   if( (AOP_TYPE(left) == AOP_PCODE) 
11163       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11164           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11165     {
11166       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11167       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11168       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11169       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11170       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11171       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11172   } else {
11173     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11174     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11175     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11176   }
11177
11178   while(size--) {
11179     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11180     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11181     offset++;
11182   }
11183     
11184   pic16_freeAsmop(left,NULL,ic,TRUE);
11185   pic16_freeAsmop(result,NULL,ic,TRUE);
11186 }
11187
11188
11189 /*-----------------------------------------------------------------*/
11190 /* genPointerGet - generate code for pointer get                   */
11191 /*-----------------------------------------------------------------*/
11192 static void genPointerGet (iCode *ic)
11193 {
11194   operand *left, *result ;
11195   sym_link *type, *etype;
11196   int p_type;
11197
11198     FENTRY;
11199     
11200     left = IC_LEFT(ic);
11201     result = IC_RESULT(ic) ;
11202
11203     /* depending on the type of pointer we need to
11204     move it to the correct pointer register */
11205     type = operandType(left);
11206     etype = getSpec(type);
11207
11208 #if 0
11209     if (IS_PTR_CONST(type))
11210 #else
11211     if (IS_CODEPTR(type))
11212 #endif
11213       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11214
11215     /* if left is of type of pointer then it is simple */
11216     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11217       p_type = DCL_TYPE(type);
11218     else {
11219       /* we have to go by the storage class */
11220       p_type = PTR_TYPE(SPEC_OCLS(etype));
11221
11222       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11223
11224       if (SPEC_OCLS(etype)->codesp ) {
11225         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11226         //p_type = CPOINTER ;   
11227       } else
11228       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11229         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11230         /*p_type = FPOINTER ;*/ 
11231       } else
11232       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11233         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11234         /* p_type = PPOINTER; */
11235       } else
11236       if (SPEC_OCLS(etype) == idata ) {
11237         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11238         /* p_type = IPOINTER; */
11239       } else {
11240         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11241         /* p_type = POINTER ; */
11242       }
11243     }
11244
11245     /* now that we have the pointer type we assign
11246     the pointer values */
11247     switch (p_type) {
11248       case POINTER:     
11249       case FPOINTER:
11250       case IPOINTER:
11251         genNearPointerGet (left,result,ic);
11252         break;
11253
11254       case PPOINTER:
11255         genPagedPointerGet(left,result,ic);
11256         break;
11257
11258 #if 0
11259       /* PICs do not support FAR pointers... */
11260       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11261       case FPOINTER:
11262         genFarPointerGet (left,result,ic);
11263         break;
11264 #endif
11265
11266       case CPOINTER:
11267         genConstPointerGet (left,result,ic);
11268         //pic16_emitcodePointerGet (left,result,ic);
11269         break;
11270
11271       case GPOINTER:
11272 #if 0
11273       if (IS_PTR_CONST(type))
11274         genConstPointerGet (left,result,ic);
11275       else
11276 #endif
11277         genGenPointerGet (left,result,ic);
11278       break;
11279
11280     default:
11281       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11282               "genPointerGet: illegal pointer type");
11283     
11284     }
11285 }
11286
11287 /*-----------------------------------------------------------------*/
11288 /* genPackBits - generates code for packed bit storage             */
11289 /*-----------------------------------------------------------------*/
11290 static void genPackBits (sym_link    *etype , operand *result,
11291                          operand *right ,
11292                          char *rname, int p_type)
11293 {
11294   int shCnt = 0 ;
11295   int offset = 0  ;
11296   int rLen = 0 ;
11297   int blen, bstr ;   
11298   int shifted_and_masked = 0;
11299   unsigned long lit = (unsigned long)-1;
11300   sym_link *retype;
11301
11302   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11303   blen = SPEC_BLEN(etype);
11304   bstr = SPEC_BSTR(etype);
11305
11306   retype = getSpec(operandType(right));
11307
11308   if(AOP_TYPE(right) == AOP_LIT) {
11309     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11310     
11311     if((blen == 1) && (bstr < 8)) {
11312       /* it is a single bit, so use the appropriate bit instructions */
11313
11314       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11315
11316       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11317         /* workaround to reduce the extra lfsr instruction */
11318         if(lit) {
11319           pic16_emitpcode(POC_BSF,
11320               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11321         } else {
11322           pic16_emitpcode(POC_BCF,
11323               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11324         }
11325       } else {
11326         if (PIC_IS_DATA_PTR(operandType(result))) {
11327           pic16_loadFSR0(result, 0);
11328           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11329               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11330         } else {
11331           /* get old value */
11332           pic16_derefPtr (result, p_type, 0, NULL);
11333           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11334               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11335           /* write back new value */
11336           pic16_derefPtr (result, p_type, 1, NULL);
11337         }
11338       }
11339
11340       return;
11341     }
11342     /* IORLW below is more efficient */
11343     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11344     lit = (lit & ((1UL << blen) - 1)) << bstr;
11345     shifted_and_masked = 1;
11346     offset++;
11347   } else
11348     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11349         && IS_BITFIELD(retype) 
11350         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11351         && (blen == 1)) {
11352       int rblen, rbstr;
11353
11354       rblen = SPEC_BLEN( retype );
11355       rbstr = SPEC_BSTR( retype );
11356
11357       if(IS_BITFIELD(etype)) {
11358         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11359         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11360       } else {
11361         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11362       }
11363
11364       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11365
11366       if(IS_BITFIELD(etype)) {
11367         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11368       } else {
11369         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11370       }
11371
11372       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11373
11374       return;
11375     } else {
11376       /* move right to W */
11377       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11378     }
11379
11380   /* if the bit length is less than or   */
11381   /* it exactly fits a byte then         */
11382   if((shCnt=SPEC_BSTR(etype))
11383       || SPEC_BLEN(etype) <= 8 )  {
11384     int fsr0_setup = 0;
11385
11386     if (blen != 8 || bstr != 0) {
11387       // we need to combine the value with the old value
11388       if(!shifted_and_masked)
11389       {
11390         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11391
11392         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11393             SPEC_BSTR(etype), SPEC_BLEN(etype));
11394
11395         /* shift left acc, do NOT mask the result again */
11396         AccLsh(shCnt, 0);
11397
11398         /* using PRODH as a temporary register here */
11399         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11400       }
11401
11402       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11403         || IS_DIRECT(result)) {
11404         /* access symbol directly */
11405         pic16_mov2w (AOP(result), 0);
11406       } else {
11407         /* get old value */
11408         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11409       }
11410 #if 1
11411       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11412             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11413                             (unsigned char)(0xff >> (8-bstr))) ));
11414       if (!shifted_and_masked) {
11415         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11416       } else {
11417         /* We have the shifted and masked (literal) right value in `lit' */
11418         if (lit != 0)
11419           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11420       }
11421     } // if (blen != 8 || bstr != 0)
11422
11423     /* write new value back */
11424     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11425         || IS_DIRECT(result)) {
11426       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11427     } else {
11428       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11429     }
11430 #endif
11431
11432     return;
11433   }
11434
11435
11436 #if 0
11437   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11438   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11439   exit(-1);
11440 #endif
11441
11442
11443   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11444   rLen = SPEC_BLEN(etype)-8;
11445
11446   /* now generate for lengths greater than one byte */
11447   while (1) {
11448     rLen -= 8 ;
11449     if (rLen <= 0 ) {
11450       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11451       break ;
11452     }
11453
11454     switch (p_type) {
11455       case POINTER:
11456         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11457         break;
11458
11459         /*
11460            case FPOINTER:
11461            MOVA(l);
11462            pic16_emitcode("movx","@dptr,a");
11463            break;
11464
11465            case GPOINTER:
11466            MOVA(l);
11467            DEBUGpic16_emitcode(";lcall","__gptrput");
11468            break;  
11469          */
11470       default:
11471         assert(0);
11472     }   
11473
11474
11475     pic16_mov2w(AOP(right), offset++);
11476   }
11477
11478   /* last last was not complete */
11479   if (rLen)   {
11480     /* save the byte & read byte */
11481     switch (p_type) {
11482       case POINTER:
11483         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11484         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11485         break;
11486
11487         /*
11488            case FPOINTER:
11489            pic16_emitcode ("mov","b,a");
11490            pic16_emitcode("movx","a,@dptr");
11491            break;
11492
11493            case GPOINTER:
11494            pic16_emitcode ("push","b");
11495            pic16_emitcode ("push","acc");
11496            pic16_emitcode ("lcall","__gptrget");
11497            pic16_emitcode ("pop","b");
11498            break;
11499          */
11500       default:
11501         assert(0);
11502     }
11503     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11504     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11505     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11506     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11507     //        pic16_emitcode ("orl","a,b");
11508   }
11509
11510   //    if (p_type == GPOINTER)
11511   //        pic16_emitcode("pop","b");
11512
11513   switch (p_type) {
11514
11515     case POINTER:
11516       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11517       //        pic16_emitcode("mov","@%s,a",rname);
11518       break;
11519       /*
11520          case FPOINTER:
11521          pic16_emitcode("movx","@dptr,a");
11522          break;
11523
11524          case GPOINTER:
11525          DEBUGpic16_emitcode(";lcall","__gptrput");
11526          break;                 
11527        */
11528     default:
11529       assert(0);
11530   }
11531
11532   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11533 }
11534
11535 /*-----------------------------------------------------------------*/
11536 /* genDataPointerSet - remat pointer to data space                 */
11537 /*-----------------------------------------------------------------*/
11538 static void genDataPointerSet(operand *right,
11539                               operand *result,
11540                               iCode *ic)
11541 {
11542   int size, offset = 0, resoffset=0 ;
11543
11544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11545     pic16_aopOp(right,ic,FALSE);
11546
11547     size = AOP_SIZE(right);
11548
11549 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11550
11551 #if 0
11552     if ( AOP_TYPE(result) == AOP_PCODE) {
11553       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11554               AOP(result)->aopu.pcop->name,
11555                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11556               PCOR(AOP(result)->aopu.pcop)->instance:
11557               PCOI(AOP(result)->aopu.pcop)->offset);
11558     }
11559 #endif
11560
11561     if(AOP(result)->aopu.pcop->type == PO_DIR)
11562       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11563
11564     while (size--) {
11565       if (AOP_TYPE(right) == AOP_LIT) {
11566         unsigned int lit;
11567
11568           if(!IS_FLOAT(operandType( right )))
11569             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11570           else {
11571             union {
11572               unsigned long lit_int;
11573               float lit_float;
11574             } info;
11575         
11576               /* take care if literal is a float */
11577               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11578               lit = info.lit_int;
11579           }
11580                     lit = lit >> (8*offset);
11581                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11582                 } else {
11583                   pic16_mov2w(AOP(right), offset);
11584                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11585                 }
11586                 offset++;
11587                 resoffset++;
11588         }
11589
11590     pic16_freeAsmop(right,NULL,ic,TRUE);
11591 }
11592
11593
11594
11595 /*-----------------------------------------------------------------*/
11596 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11597 /*-----------------------------------------------------------------*/
11598 static void genNearPointerSet (operand *right,
11599                                operand *result, 
11600                                iCode *ic)
11601 {
11602   asmop *aop = NULL;
11603   sym_link *retype;
11604   sym_link *ptype = operandType(result);
11605   sym_link *resetype;
11606     
11607     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11608     retype= getSpec(operandType(right));
11609     resetype = getSpec(operandType(result));
11610   
11611     pic16_aopOp(result,ic,FALSE);
11612     
11613     /* if the result is rematerializable &
11614      * in data space & not a bit variable */
11615         
11616     /* and result is not a bit variable */
11617     if (AOP_TYPE(result) == AOP_PCODE
11618 //      && AOP_TYPE(result) == AOP_IMMD
11619       && DCL_TYPE(ptype) == POINTER
11620       && !IS_BITFIELD(retype)
11621       && !IS_BITFIELD(resetype)) {
11622
11623         genDataPointerSet (right,result,ic);
11624         pic16_freeAsmop(result,NULL,ic,TRUE);
11625       return;
11626     }
11627
11628     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11629     pic16_aopOp(right,ic,FALSE);
11630     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11631
11632     /* if bitfield then unpack the bits */
11633     if (IS_BITFIELD(resetype)) {
11634       genPackBits (resetype, result, right, NULL, POINTER);
11635     } else {
11636       /* we have can just get the values */
11637       int size = AOP_SIZE(right);
11638       int offset = 0 ;    
11639
11640         pic16_loadFSR0(result, 0);
11641             
11642         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11643         while (size--) {
11644           if (AOP_TYPE(right) == AOP_LIT) {
11645             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11646             if (size) {
11647               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11648             } else {
11649               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11650             }
11651           } else { // no literal
11652             if(size) {
11653               pic16_emitpcode(POC_MOVFF,
11654                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11655                   pic16_popCopyReg(&pic16_pc_postinc0)));
11656             } else {
11657               pic16_emitpcode(POC_MOVFF,
11658                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11659                   pic16_popCopyReg(&pic16_pc_indf0)));
11660             }
11661           }
11662           
11663           offset++;
11664         }
11665     }
11666
11667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11668     /* now some housekeeping stuff */
11669     if (aop) {
11670       /* we had to allocate for this iCode */
11671       pic16_freeAsmop(NULL,aop,ic,TRUE);
11672     } else { 
11673       /* we did not allocate which means left
11674        * already in a pointer register, then
11675        * if size > 0 && this could be used again
11676        * we have to point it back to where it 
11677        * belongs */
11678       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11679       if (AOP_SIZE(right) > 1
11680         && !OP_SYMBOL(result)->remat
11681         && ( OP_SYMBOL(result)->liveTo > ic->seq
11682         || ic->depth )) {
11683
11684           int size = AOP_SIZE(right) - 1;
11685
11686             while (size--)
11687               pic16_emitcode("decf","fsr0,f");
11688               //pic16_emitcode("dec","%s",rname);
11689       }
11690     }
11691
11692     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11693     /* done */
11694 //release:
11695     pic16_freeAsmop(right,NULL,ic,TRUE);
11696     pic16_freeAsmop(result,NULL,ic,TRUE);
11697 }
11698
11699 /*-----------------------------------------------------------------*/
11700 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11701 /*-----------------------------------------------------------------*/
11702 static void genPagedPointerSet (operand *right,
11703                                operand *result, 
11704                                iCode *ic)
11705 {
11706     asmop *aop = NULL;
11707     regs *preg = NULL ;
11708     char *rname , *l;
11709     sym_link *retype;
11710        
11711     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11712
11713     retype= getSpec(operandType(right));
11714     
11715     pic16_aopOp(result,ic,FALSE);
11716     
11717     /* if the value is already in a pointer register
11718        then don't need anything more */
11719     if (!AOP_INPREG(AOP(result))) {
11720         /* otherwise get a free pointer register */
11721         aop = newAsmop(0);
11722         preg = getFreePtr(ic,&aop,FALSE);
11723         pic16_emitcode("mov","%s,%s",
11724                 preg->name,
11725                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11726         rname = preg->name ;
11727     } else
11728         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11729     
11730     pic16_freeAsmop(result,NULL,ic,TRUE);
11731     pic16_aopOp (right,ic,FALSE);
11732
11733     /* if bitfield then unpack the bits */
11734     if (IS_BITFIELD(retype)) 
11735         genPackBits (retype,result,right,rname,PPOINTER);
11736     else {
11737         /* we have can just get the values */
11738         int size = AOP_SIZE(right);
11739         int offset = 0 ;        
11740         
11741         while (size--) {
11742             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11743             
11744             MOVA(l);
11745             pic16_emitcode("movx","@%s,a",rname);
11746
11747             if (size)
11748                 pic16_emitcode("inc","%s",rname);
11749
11750             offset++;
11751         }
11752     }
11753     
11754     /* now some housekeeping stuff */
11755     if (aop) {
11756         /* we had to allocate for this iCode */
11757         pic16_freeAsmop(NULL,aop,ic,TRUE);
11758     } else { 
11759         /* we did not allocate which means left
11760            already in a pointer register, then
11761            if size > 0 && this could be used again
11762            we have to point it back to where it 
11763            belongs */
11764         if (AOP_SIZE(right) > 1 &&
11765             !OP_SYMBOL(result)->remat &&
11766             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11767               ic->depth )) {
11768             int size = AOP_SIZE(right) - 1;
11769             while (size--)
11770                 pic16_emitcode("dec","%s",rname);
11771         }
11772     }
11773
11774     /* done */
11775     pic16_freeAsmop(right,NULL,ic,TRUE);
11776     
11777         
11778 }
11779
11780 #if 0
11781 /* This code is not adjusted to PIC16 and fails utterly...
11782  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11783
11784 /*-----------------------------------------------------------------*/
11785 /* genFarPointerSet - set value from far space                     */
11786 /*-----------------------------------------------------------------*/
11787 static void genFarPointerSet (operand *right,
11788                               operand *result, iCode *ic)
11789 {
11790     int size, offset ;
11791     sym_link *retype = getSpec(operandType(right));
11792
11793     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11794     pic16_aopOp(result,ic,FALSE);
11795
11796     /* if the operand is already in dptr 
11797     then we do nothing else we move the value to dptr */
11798     if (AOP_TYPE(result) != AOP_STR) {
11799         /* if this is remateriazable */
11800         if (AOP_TYPE(result) == AOP_IMMD)
11801             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11802         else { /* we need to get it byte by byte */
11803             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11804             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11805             if (options.model == MODEL_FLAT24)
11806             {
11807                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11808             }
11809         }
11810     }
11811     /* so dptr know contains the address */
11812     pic16_freeAsmop(result,NULL,ic,TRUE);
11813     pic16_aopOp(right,ic,FALSE);
11814
11815     /* if bit then unpack */
11816     if (IS_BITFIELD(retype)) 
11817         genPackBits(retype,result,right,"dptr",FPOINTER);
11818     else {
11819         size = AOP_SIZE(right);
11820         offset = 0 ;
11821
11822         while (size--) {
11823             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11824             MOVA(l);
11825             pic16_emitcode("movx","@dptr,a");
11826             if (size)
11827                 pic16_emitcode("inc","dptr");
11828         }
11829     }
11830
11831     pic16_freeAsmop(right,NULL,ic,TRUE);
11832 }
11833 #endif
11834
11835 /*-----------------------------------------------------------------*/
11836 /* genGenPointerSet - set value from generic pointer space         */
11837 /*-----------------------------------------------------------------*/
11838 #if 0
11839 static void genGenPointerSet (operand *right,
11840                               operand *result, iCode *ic)
11841 {
11842         int i, size, offset, lit;
11843         sym_link *retype = getSpec(operandType(right));
11844
11845         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11846
11847         pic16_aopOp(result,ic,FALSE);
11848         pic16_aopOp(right,ic,FALSE);
11849         size = AOP_SIZE(right);
11850         offset = 0;
11851
11852         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11853
11854         /* if the operand is already in dptr 
11855                 then we do nothing else we move the value to dptr */
11856         if (AOP_TYPE(result) != AOP_STR) {
11857                 /* if this is remateriazable */
11858                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11859                 // WARNING: anythig until "else" is untested!
11860                 if (AOP_TYPE(result) == AOP_IMMD) {
11861                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11862                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11863                         // load FSR0 from immediate
11864                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11865                         offset = 0;
11866                         while(size--) {
11867                                 if(size) {
11868                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11869                                 } else {
11870                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11871                                 }
11872                                 offset++;
11873                         }
11874                         goto release;
11875                 }
11876                 else { /* we need to get it byte by byte */
11877                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11878                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11879
11880                         // set up FSR0 with address of result
11881                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11882                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11883
11884                         /* hack hack! see if this the FSR. If so don't load W */
11885                         if(AOP_TYPE(right) != AOP_ACC) {
11886
11887                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11888
11889                                 if(AOP_TYPE(right) == AOP_LIT)
11890                                 {
11891                                         // copy literal
11892                                         // note: pic16_popGet handles sign extension
11893                                         for(i=0;i<size;i++) {
11894                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11895                                                 if(i < size-1)
11896                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11897                                                 else
11898                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11899                                         }
11900                                 } else {
11901                                         // copy regs
11902
11903                                         for(i=0;i<size;i++) {
11904                                                 if(i < size-1)
11905                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11906                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11907                                                 else
11908                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11909                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11910                                         }
11911                                 }
11912                                 goto release;
11913                         } 
11914                         // right = ACC
11915                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11916                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11917                         goto release;
11918         } // if (AOP_TYPE(result) != AOP_IMMD)
11919
11920         } // if (AOP_TYPE(result) != AOP_STR)
11921         /* so dptr know contains the address */
11922
11923
11924         /* if bit then unpack */
11925         if (IS_BITFIELD(retype)) 
11926                 genPackBits(retype,result,right,"dptr",GPOINTER);
11927         else {
11928                 size = AOP_SIZE(right);
11929                 offset = 0 ;
11930
11931                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11932
11933                 // set up FSR0 with address of result
11934                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11935                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11936         
11937                 while (size--) {
11938                         if (AOP_TYPE(right) == AOP_LIT) {
11939                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11940                                 if (size) {
11941                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11942                                 } else {
11943                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11944                                 }
11945                         } else { // no literal
11946                                 if(size) {
11947                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11948                                 } else {
11949                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11950                                 }
11951                         }
11952                         offset++;
11953                 }
11954         }
11955
11956         release:
11957         pic16_freeAsmop(right,NULL,ic,TRUE);
11958         pic16_freeAsmop(result,NULL,ic,TRUE);
11959 }
11960 #endif
11961
11962 static void genGenPointerSet (operand *right,
11963                               operand *result, iCode *ic)
11964 {
11965   int size;
11966   sym_link *retype = getSpec(operandType(result));
11967
11968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11969
11970     pic16_aopOp(result,ic,FALSE);
11971     pic16_aopOp(right,ic,FALSE);
11972     size = AOP_SIZE(right);
11973
11974     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11975
11976
11977     /* if bit then unpack */
11978     if (IS_BITFIELD(retype)) {
11979 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11980       genPackBits(retype,result,right,"dptr",GPOINTER);
11981       goto release;
11982     }
11983
11984     size = AOP_SIZE(right);
11985
11986     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11987
11988
11989     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11990
11991     /* value of right+0 is placed on stack, which will be retrieved
11992      * by the support function thus restoring the stack. The important
11993      * thing is that there is no need to manually restore stack pointer
11994      * here */
11995     pushaop(AOP(right), 0);
11996 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11997     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11998     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11999     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12000     
12001     /* load address to write to in WREG:FSR0H:FSR0L */
12002     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12003                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12004     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12005                                 pic16_popCopyReg(&pic16_pc_prodl)));
12006     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12007     
12008     pic16_callGenericPointerRW(1, size);
12009
12010 release:
12011     pic16_freeAsmop(right,NULL,ic,TRUE);
12012     pic16_freeAsmop(result,NULL,ic,TRUE);
12013 }
12014
12015 /*-----------------------------------------------------------------*/
12016 /* genPointerSet - stores the value into a pointer location        */
12017 /*-----------------------------------------------------------------*/
12018 static void genPointerSet (iCode *ic)
12019 {    
12020   operand *right, *result ;
12021   sym_link *type, *etype;
12022   int p_type;
12023
12024     FENTRY;
12025
12026     right = IC_RIGHT(ic);
12027     result = IC_RESULT(ic) ;
12028
12029     /* depending on the type of pointer we need to
12030     move it to the correct pointer register */
12031     type = operandType(result);
12032     etype = getSpec(type);
12033     
12034     /* if left is of type of pointer then it is simple */
12035     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12036         p_type = DCL_TYPE(type);
12037     }
12038     else {
12039         /* we have to go by the storage class */
12040         p_type = PTR_TYPE(SPEC_OCLS(etype));
12041
12042 /*      if (SPEC_OCLS(etype)->codesp ) { */
12043 /*          p_type = CPOINTER ;  */
12044 /*      } */
12045 /*      else */
12046 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12047 /*              p_type = FPOINTER ; */
12048 /*          else */
12049 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12050 /*                  p_type = PPOINTER ; */
12051 /*              else */
12052 /*                  if (SPEC_OCLS(etype) == idata ) */
12053 /*                      p_type = IPOINTER ; */
12054 /*                  else */
12055 /*                      p_type = POINTER ; */
12056     }
12057
12058     /* now that we have the pointer type we assign
12059     the pointer values */
12060     switch (p_type) {
12061       case POINTER:
12062       case FPOINTER:
12063       case IPOINTER:
12064         genNearPointerSet (right,result,ic);
12065         break;
12066
12067       case PPOINTER:
12068         genPagedPointerSet (right,result,ic);
12069         break;
12070
12071 #if 0
12072       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12073       case FPOINTER:
12074         genFarPointerSet (right,result,ic);
12075         break;
12076 #endif
12077         
12078       case GPOINTER:
12079         genGenPointerSet (right,result,ic);
12080         break;
12081
12082       default:
12083         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12084           "genPointerSet: illegal pointer type");
12085     }
12086 }
12087
12088 /*-----------------------------------------------------------------*/
12089 /* genIfx - generate code for Ifx statement                        */
12090 /*-----------------------------------------------------------------*/
12091 static void genIfx (iCode *ic, iCode *popIc)
12092 {
12093   operand *cond = IC_COND(ic);
12094   int isbit =0;
12095
12096     FENTRY;
12097
12098     pic16_aopOp(cond,ic,FALSE);
12099
12100     /* get the value into acc */
12101     if (AOP_TYPE(cond) != AOP_CRY)
12102       pic16_toBoolean(cond);
12103     else
12104       isbit = 1;
12105     /* the result is now in the accumulator */
12106     pic16_freeAsmop(cond,NULL,ic,TRUE);
12107
12108     /* if there was something to be popped then do it */
12109     if (popIc)
12110       genIpop(popIc);
12111
12112     /* if the condition is  a bit variable */
12113     if (isbit && IS_ITEMP(cond) && 
12114         SPIL_LOC(cond)) {
12115       genIfxJump(ic,"c");
12116       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12117     } else {
12118       if (isbit && !IS_ITEMP(cond))
12119         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12120         else
12121         genIfxJump(ic,"a");
12122     }
12123     ic->generated = 1;
12124 }
12125
12126 /*-----------------------------------------------------------------*/
12127 /* genAddrOf - generates code for address of                       */
12128 /*-----------------------------------------------------------------*/
12129 static void genAddrOf (iCode *ic)
12130 {
12131   operand *result, *left;
12132   int size;
12133   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12134   pCodeOp *pcop0, *pcop1, *pcop2;
12135
12136     FENTRY;
12137
12138     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12139
12140     sym = OP_SYMBOL( IC_LEFT(ic) );
12141     
12142     if(sym->onStack) {
12143       /* get address of symbol on stack */
12144       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12145 #if 0
12146       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12147                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12148 #endif
12149
12150       // operands on stack are accessible via "FSR2 + index" with index
12151       // starting at 2 for arguments and growing from 0 downwards for
12152       // local variables (index == 0 is not assigned so we add one here)
12153       {
12154         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12155
12156           if (soffs <= 0) {
12157             assert (soffs < 0);
12158             soffs++;
12159           } // if
12160
12161           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12162           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12163           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12164           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12165           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12166           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12167           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12168       }
12169
12170       goto release;
12171     }
12172         
12173 //      if(pic16_debug_verbose) {
12174 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12175 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12176 //      }
12177         
12178     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12179     size = AOP_SIZE(IC_RESULT(ic));
12180
12181     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12182     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12183     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12184         
12185     if (size == 3) {
12186       pic16_emitpcode(POC_MOVLW, pcop0);
12187       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12188       pic16_emitpcode(POC_MOVLW, pcop1);
12189       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12190       pic16_emitpcode(POC_MOVLW, pcop2);
12191       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12192     } else
12193     if (size == 2) {
12194       pic16_emitpcode(POC_MOVLW, pcop0);
12195       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12196       pic16_emitpcode(POC_MOVLW, pcop1);
12197     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12198     } else {
12199       pic16_emitpcode(POC_MOVLW, pcop0);
12200       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12201     }
12202
12203     pic16_freeAsmop(left, NULL, ic, FALSE);
12204 release:
12205     pic16_freeAsmop(result,NULL,ic,TRUE);
12206 }
12207
12208
12209 #if 0
12210 /*-----------------------------------------------------------------*/
12211 /* genFarFarAssign - assignment when both are in far space         */
12212 /*-----------------------------------------------------------------*/
12213 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12214 {
12215     int size = AOP_SIZE(right);
12216     int offset = 0;
12217     char *l ;
12218     /* first push the right side on to the stack */
12219     while (size--) {
12220         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12221         MOVA(l);
12222         pic16_emitcode ("push","acc");
12223     }
12224     
12225     pic16_freeAsmop(right,NULL,ic,FALSE);
12226     /* now assign DPTR to result */
12227     pic16_aopOp(result,ic,FALSE);
12228     size = AOP_SIZE(result);
12229     while (size--) {
12230         pic16_emitcode ("pop","acc");
12231         pic16_aopPut(AOP(result),"a",--offset);
12232     }
12233     pic16_freeAsmop(result,NULL,ic,FALSE);
12234         
12235 }
12236 #endif
12237
12238 /*-----------------------------------------------------------------*/
12239 /* genAssign - generate code for assignment                        */
12240 /*-----------------------------------------------------------------*/
12241 static void genAssign (iCode *ic)
12242 {
12243   operand *result, *right;
12244   sym_link *restype, *rtype;
12245   int size, offset,know_W;
12246   unsigned long lit = 0L;
12247
12248     result = IC_RESULT(ic);
12249     right  = IC_RIGHT(ic) ;
12250
12251     FENTRY;
12252   
12253     /* if they are the same */
12254     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12255       return ;
12256
12257     /* reversed order operands are aopOp'ed so that result operand
12258      * is effective in case right is a stack symbol. This maneauver
12259      * allows to use the _G.resDirect flag later */
12260      pic16_aopOp(result,ic,TRUE);
12261     pic16_aopOp(right,ic,FALSE);
12262
12263     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12264
12265     /* if they are the same registers */
12266     if (pic16_sameRegs(AOP(right),AOP(result)))
12267       goto release;
12268
12269     /* if the result is a bit */
12270     if (AOP_TYPE(result) == AOP_CRY) {
12271       /* if the right size is a literal then
12272          we know what the value is */
12273       if (AOP_TYPE(right) == AOP_LIT) {
12274           
12275         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12276             pic16_popGet(AOP(result),0));
12277
12278         if (((int) operandLitValue(right))) 
12279           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12280               AOP(result)->aopu.aop_dir,
12281               AOP(result)->aopu.aop_dir);
12282         else
12283           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12284               AOP(result)->aopu.aop_dir,
12285               AOP(result)->aopu.aop_dir);
12286         
12287         goto release;
12288       }
12289
12290       /* the right is also a bit variable */
12291       if (AOP_TYPE(right) == AOP_CRY) {
12292         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12293         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12294         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12295
12296         goto release ;
12297       }
12298
12299       /* we need to or */
12300       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12301       pic16_toBoolean(right);
12302       emitSKPZ;
12303       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12304       //pic16_aopPut(AOP(result),"a",0);
12305       goto release ;
12306     }
12307
12308     /* bit variables done */
12309     /* general case */
12310     size = AOP_SIZE(result);
12311     offset = 0 ;
12312
12313   /* bit variables done */
12314   /* general case */
12315   size = AOP_SIZE(result);
12316   restype = operandType(result);
12317   rtype = operandType(right);
12318   offset = 0 ;
12319
12320   if(AOP_TYPE(right) == AOP_LIT) {
12321     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12322     {
12323       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12324
12325       /* patch tag for literals that are cast to pointers */
12326       if (IS_CODEPTR(restype)) {
12327         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12328         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12329       } else {
12330         if (IS_GENPTR(restype))
12331         {
12332           if (IS_CODEPTR(rtype)) {
12333             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12334             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12335           } else if (PIC_IS_DATA_PTR(rtype)) {
12336             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12337             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12338           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12339             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12340           } else if (IS_PTR(rtype)) {
12341             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12342             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12343           }
12344         }
12345       }
12346     } else {
12347       union {
12348         unsigned long lit_int;
12349         float lit_float;
12350       } info;
12351
12352
12353       if(IS_FIXED16X16(operandType(right))) {
12354         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12355       } else {
12356         /* take care if literal is a float */
12357         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12358         lit = info.lit_int;
12359       }
12360     }
12361   }
12362
12363 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12364 //                      sizeof(unsigned long int), sizeof(float));
12365
12366
12367     if (AOP_TYPE(right) == AOP_REG) {
12368       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12369       while (size--) {
12370         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12371       } // while
12372       goto release;
12373     }
12374
12375     /* when do we have to read the program memory?
12376      * - if right itself is a symbol in code space
12377      *   (we don't care what it points to if it's a pointer)
12378      * - AND right is not a function (we would want its address)
12379      */
12380     if(AOP_TYPE(right) != AOP_LIT
12381       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12382       && !IS_FUNC(OP_SYM_TYPE(right))
12383       && !IS_ITEMP(right)) {
12384
12385       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12386       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12387       
12388       // set up table pointer
12389       if(is_LitOp(right)) {
12390 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12391         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12392         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12393         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12394         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12395         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12396         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12397       } else {
12398 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12399         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12400             pic16_popCopyReg(&pic16_pc_tblptrl)));
12401         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12402             pic16_popCopyReg(&pic16_pc_tblptrh)));
12403         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12404             pic16_popCopyReg(&pic16_pc_tblptru)));
12405       }
12406
12407       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12408       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12409       while(size--) {
12410         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12411         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12412             pic16_popGet(AOP(result),offset)));
12413         offset++;
12414       }
12415
12416       /* FIXME: for pointers we need to extend differently (according
12417        * to pointer type DATA/CODE/EEPROM/... :*/
12418       size = getSize(OP_SYM_TYPE(right));
12419       if(AOP_SIZE(result) > size) {
12420         size = AOP_SIZE(result) - size;
12421         while(size--) {
12422           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12423           offset++;
12424         }
12425       }
12426       goto release;
12427     }
12428
12429 #if 0
12430     /* VR - What is this?! */
12431     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12432       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12433       
12434       if(aopIdx(AOP(result),0) == 4) {
12435         /* this is a workaround to save value of right into wreg too,
12436          * value of wreg is going to be used later */
12437         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12438         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12439         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12440         goto release;
12441       } else
12442 //      assert(0);
12443       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12444     }
12445 #endif
12446
12447   know_W=-1;
12448   while (size--) {
12449     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12450     if(AOP_TYPE(right) == AOP_LIT) {
12451       if(lit&0xff) {
12452         if(know_W != (lit&0xff))
12453           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12454         know_W = lit&0xff;
12455         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12456       } else
12457         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12458
12459       lit >>= 8;
12460
12461     } else if (AOP_TYPE(right) == AOP_CRY) {
12462       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12463       if(offset == 0) {
12464         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12465         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12466         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12467       }
12468     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12469         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12470         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12471     } else {
12472       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12473
12474       if(!_G.resDirect)         /* use this aopForSym feature */
12475         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12476     }
12477       
12478       offset++;
12479     }
12480   
12481 release:
12482   pic16_freeAsmop (right,NULL,ic,FALSE);
12483   pic16_freeAsmop (result,NULL,ic,TRUE);
12484
12485
12486 /*-----------------------------------------------------------------*/
12487 /* genJumpTab - generates code for jump table                       */
12488 /*-----------------------------------------------------------------*/
12489 static void genJumpTab (iCode *ic)
12490 {
12491   symbol *jtab;
12492   char *l;
12493   pCodeOp *jt_offs;
12494   pCodeOp *jt_offs_hi;
12495   pCodeOp *jt_label;
12496
12497     FENTRY;
12498
12499     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12500     /* get the condition into accumulator */
12501     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12502     MOVA(l);
12503     /* multiply by three */
12504     pic16_emitcode("add","a,acc");
12505     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12506
12507     jtab = newiTempLabel(NULL);
12508     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12509     pic16_emitcode("jmp","@a+dptr");
12510     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12511
12512 #if 0
12513     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12514     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12515     emitSKPNC;
12516     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12517     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12518     pic16_emitpLabel(jtab->key);
12519
12520 #else
12521
12522     jt_offs = pic16_popGetTempReg(0);
12523     jt_offs_hi = pic16_popGetTempReg(1);
12524     jt_label = pic16_popGetLabel (jtab->key);
12525     //fprintf (stderr, "Creating jump table...\n");
12526
12527     // calculate offset into jump table (idx * sizeof (GOTO))
12528     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12529     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12530     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12531     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12532     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12533     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12534     pic16_emitpcode(POC_MOVWF , jt_offs);
12535
12536     // prepare PCLATx (set to first entry in jump table)
12537     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12538     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12539     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12540     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12541     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12542
12543     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12544     pic16_emitpcode(POC_ADDWF , jt_offs);
12545     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12546     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12547     emitSKPNC;
12548     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12549
12550     // release temporaries and prepare jump into table (new PCL --> WREG)
12551     pic16_emitpcode(POC_MOVFW , jt_offs);
12552     pic16_popReleaseTempReg (jt_offs_hi, 1);
12553     pic16_popReleaseTempReg (jt_offs, 0);
12554
12555     // jump into the table
12556     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12557
12558     pic16_emitpLabelFORCE(jtab->key);
12559 #endif
12560
12561     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12562 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12563
12564     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12565     /* now generate the jump labels */
12566     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12567          jtab = setNextItem(IC_JTLABELS(ic))) {
12568 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12569         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12570         
12571     }
12572     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12573
12574 }
12575
12576 /*-----------------------------------------------------------------*/
12577 /* genMixedOperation - gen code for operators between mixed types  */
12578 /*-----------------------------------------------------------------*/
12579 /*
12580   TSD - Written for the PIC port - but this unfortunately is buggy.
12581   This routine is good in that it is able to efficiently promote 
12582   types to different (larger) sizes. Unfortunately, the temporary
12583   variables that are optimized out by this routine are sometimes
12584   used in other places. So until I know how to really parse the 
12585   iCode tree, I'm going to not be using this routine :(.
12586 */
12587 static int genMixedOperation (iCode *ic)
12588 {
12589 #if 0
12590   operand *result = IC_RESULT(ic);
12591   sym_link *ctype = operandType(IC_LEFT(ic));
12592   operand *right = IC_RIGHT(ic);
12593   int ret = 0;
12594   int big,small;
12595   int offset;
12596
12597   iCode *nextic;
12598   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12599
12600   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12601
12602   nextic = ic->next;
12603   if(!nextic)
12604     return 0;
12605
12606   nextright = IC_RIGHT(nextic);
12607   nextleft  = IC_LEFT(nextic);
12608   nextresult = IC_RESULT(nextic);
12609
12610   pic16_aopOp(right,ic,FALSE);
12611   pic16_aopOp(result,ic,FALSE);
12612   pic16_aopOp(nextright,  nextic, FALSE);
12613   pic16_aopOp(nextleft,   nextic, FALSE);
12614   pic16_aopOp(nextresult, nextic, FALSE);
12615
12616   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12617
12618     operand *t = right;
12619     right = nextright;
12620     nextright = t; 
12621
12622     pic16_emitcode(";remove right +","");
12623
12624   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12625 /*
12626     operand *t = right;
12627     right = nextleft;
12628     nextleft = t; 
12629 */
12630     pic16_emitcode(";remove left +","");
12631   } else
12632     return 0;
12633
12634   big = AOP_SIZE(nextleft);
12635   small = AOP_SIZE(nextright);
12636
12637   switch(nextic->op) {
12638
12639   case '+':
12640     pic16_emitcode(";optimize a +","");
12641     /* if unsigned or not an integral type */
12642     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12643       pic16_emitcode(";add a bit to something","");
12644     } else {
12645
12646       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12647
12648       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12649         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12650         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12651       } else
12652         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12653
12654       offset = 0;
12655       while(--big) {
12656
12657         offset++;
12658
12659         if(--small) {
12660           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12661             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12662             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12663           }
12664
12665           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12666           emitSKPNC;
12667           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12668                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12669                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12670           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12671           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12672
12673         } else {
12674           pic16_emitcode("rlf","known_zero,w");
12675
12676           /*
12677             if right is signed
12678               btfsc  right,7
12679                addlw ff
12680           */
12681           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12682             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12683             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12684           } else {
12685             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12686           }
12687         }
12688       }
12689       ret = 1;
12690     }
12691   }
12692   ret = 1;
12693
12694 release:
12695   pic16_freeAsmop(right,NULL,ic,TRUE);
12696   pic16_freeAsmop(result,NULL,ic,TRUE);
12697   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12698   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12699   if(ret)
12700     nextic->generated = 1;
12701
12702   return ret;
12703 #else
12704   return 0;
12705 #endif
12706 }
12707 /*-----------------------------------------------------------------*/
12708 /* genCast - gen code for casting                                  */
12709 /*-----------------------------------------------------------------*/
12710 static void genCast (iCode *ic)
12711 {
12712   operand *result = IC_RESULT(ic);
12713   sym_link *ctype = operandType(IC_LEFT(ic));
12714   sym_link *rtype = operandType(IC_RIGHT(ic));
12715   sym_link *restype = operandType(IC_RESULT(ic));
12716   operand *right = IC_RIGHT(ic);
12717   int size, offset ;
12718
12719
12720     FENTRY;
12721
12722         /* if they are equivalent then do nothing */
12723 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12724 //              return ;
12725
12726         pic16_aopOp(result,ic,FALSE);
12727         pic16_aopOp(right,ic,FALSE) ;
12728
12729         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12730
12731
12732         /* if the result is a bit */
12733         if (AOP_TYPE(result) == AOP_CRY) {
12734         
12735                 /* if the right size is a literal then
12736                  * we know what the value is */
12737                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12738
12739                 if (AOP_TYPE(right) == AOP_LIT) {
12740                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12741                                 pic16_popGet(AOP(result),0));
12742
12743                         if (((int) operandLitValue(right))) 
12744                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12745                                         AOP(result)->aopu.aop_dir,
12746                                         AOP(result)->aopu.aop_dir);
12747                         else
12748                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12749                                         AOP(result)->aopu.aop_dir,
12750                                         AOP(result)->aopu.aop_dir);
12751                         goto release;
12752                 }
12753
12754                 /* the right is also a bit variable */
12755                 if (AOP_TYPE(right) == AOP_CRY) {
12756                         emitCLRC;
12757                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12758
12759                         pic16_emitcode("clrc","");
12760                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12761                                 AOP(right)->aopu.aop_dir,
12762                                 AOP(right)->aopu.aop_dir);
12763                         pic16_aopPut(AOP(result),"c",0);
12764                         goto release ;
12765                 }
12766
12767                 /* we need to or */
12768                 if (AOP_TYPE(right) == AOP_REG) {
12769                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12770                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12771                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12772                 }
12773                 pic16_toBoolean(right);
12774                 pic16_aopPut(AOP(result),"a",0);
12775                 goto release ;
12776         }
12777
12778         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12779           int offset = 1;
12780
12781                 size = AOP_SIZE(result);
12782
12783                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12784
12785                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12786                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12787                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12788
12789                 while (size--)
12790                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12791
12792                 goto release;
12793         }
12794
12795         if(IS_BITFIELD(getSpec(restype))
12796           && IS_BITFIELD(getSpec(rtype))) {
12797           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12798         }
12799         
12800         /* port from pic14 to cope with generic pointers */
12801         if (PIC_IS_TAGGED(restype))
12802         {
12803           operand *result = IC_RESULT(ic);
12804           //operand *left = IC_LEFT(ic);
12805           operand *right = IC_RIGHT(ic);
12806           int tag = 0xff;
12807
12808           /* copy common part */
12809           int max, size = AOP_SIZE(result);
12810           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12811           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12812
12813           max = size;
12814           while (size--)
12815           {
12816             pic16_mov2w (AOP(right), size);
12817             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12818           } // while
12819
12820           /* upcast into generic pointer type? */
12821           if (IS_GENPTR(restype)
12822               && !PIC_IS_TAGGED(rtype)
12823               && (AOP_SIZE(result) > max))
12824           {
12825             /* determine appropriate tag for right */
12826             if (PIC_IS_DATA_PTR(rtype))
12827               tag = GPTR_TAG_DATA;
12828             else if (IS_CODEPTR(rtype))
12829               tag = GPTR_TAG_CODE;
12830             else if (PIC_IS_DATA_PTR(ctype)) {
12831               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12832               tag = GPTR_TAG_DATA;
12833             } else if (IS_CODEPTR(ctype)) {
12834               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12835               tag = GPTR_TAG_CODE;
12836             } else if (IS_PTR(rtype)) {
12837               PERFORM_ONCE(weirdcast,
12838               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12839               );
12840               tag = GPTR_TAG_DATA;
12841             } else {
12842               PERFORM_ONCE(weirdcast,
12843               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12844               );
12845               tag = GPTR_TAG_DATA;
12846             }
12847
12848             assert (AOP_SIZE(result) == 3);
12849             /* zero-extend address... */
12850             for (size = max; size < AOP_SIZE(result)-1; size++)
12851               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12852             /* ...and add tag */
12853             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12854           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12855             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12856             for (size = max; size < AOP_SIZE(result)-1; size++)
12857               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12858             /* add __code tag */
12859             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12860           } else if (AOP_SIZE(result) > max) {
12861             /* extend non-pointers */
12862             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12863             pic16_addSign(result, max, 0);
12864           } // if
12865           goto release;
12866         }
12867
12868         /* if they are the same size : or less */
12869         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12870
12871                 /* if they are in the same place */
12872                 if (pic16_sameRegs(AOP(right),AOP(result)))
12873                         goto release;
12874
12875                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12876 #if 0
12877                 if (IS_PTR_CONST(rtype))
12878 #else
12879                 if (IS_CODEPTR(rtype))
12880 #endif
12881                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12882
12883 #if 0
12884                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12885 #else
12886                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12887 #endif
12888                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12889
12890 #if 0
12891                 if(AOP_TYPE(right) == AOP_IMMD) {
12892                   pCodeOp *pcop0, *pcop1, *pcop2;
12893                   symbol *sym = OP_SYMBOL( right );
12894
12895                         size = AOP_SIZE(result);
12896                         /* low */
12897                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12898                         /* high */
12899                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12900                         /* upper */
12901                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12902         
12903                         if (size == 3) {
12904                                 pic16_emitpcode(POC_MOVLW, pcop0);
12905                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12906                                 pic16_emitpcode(POC_MOVLW, pcop1);
12907                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12908                                 pic16_emitpcode(POC_MOVLW, pcop2);
12909                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12910                         } else
12911                         if (size == 2) {
12912                                 pic16_emitpcode(POC_MOVLW, pcop0);
12913                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12914                                 pic16_emitpcode(POC_MOVLW, pcop1);
12915                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12916                         } else {
12917                                 pic16_emitpcode(POC_MOVLW, pcop0);
12918                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12919                         }
12920                 } else
12921 #endif
12922                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12923                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12924                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12925                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12926                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12927                         if(AOP_SIZE(result) <2)
12928                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12929                 } else {
12930                         /* if they in different places then copy */
12931                         size = AOP_SIZE(result);
12932                         offset = 0 ;
12933                         while (size--) {
12934                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12935                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12936                                 offset++;
12937                         }
12938                 }
12939                 goto release;
12940         }
12941
12942         /* if the result is of type pointer */
12943         if (IS_PTR(ctype)) {
12944           int p_type;
12945           sym_link *type = operandType(right);
12946           sym_link *etype = getSpec(type);
12947
12948                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12949
12950                 /* pointer to generic pointer */
12951                 if (IS_GENPTR(ctype)) {
12952                   char *l = zero;
12953             
12954                         if (IS_PTR(type)) 
12955                                 p_type = DCL_TYPE(type);
12956                         else {
12957                 /* we have to go by the storage class */
12958                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12959
12960 /*              if (SPEC_OCLS(etype)->codesp )  */
12961 /*                  p_type = CPOINTER ;  */
12962 /*              else */
12963 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12964 /*                      p_type = FPOINTER ; */
12965 /*                  else */
12966 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12967 /*                          p_type = PPOINTER; */
12968 /*                      else */
12969 /*                          if (SPEC_OCLS(etype) == idata ) */
12970 /*                              p_type = IPOINTER ; */
12971 /*                          else */
12972 /*                              p_type = POINTER ; */
12973             }
12974                 
12975             /* the first two bytes are known */
12976       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12977             size = GPTRSIZE - 1; 
12978             offset = 0 ;
12979             while (size--) {
12980               if(offset < AOP_SIZE(right)) {
12981                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12982                 pic16_mov2f(AOP(result), AOP(right), offset);
12983 /*
12984                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12985                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12986                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12987                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12988                 } else { 
12989                   
12990                   pic16_aopPut(AOP(result),
12991                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12992                          offset);
12993                 }
12994 */
12995               } else 
12996                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12997               offset++;
12998             }
12999             /* the last byte depending on type */
13000             switch (p_type) {
13001             case IPOINTER:
13002             case POINTER:
13003             case FPOINTER:
13004                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13005                 break;
13006
13007             case CPOINTER:
13008                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13009                 break;
13010
13011             case PPOINTER:
13012               pic16_emitcode(";BUG!? ","%d",__LINE__);
13013                 l = "#0x03";
13014                 break;
13015
13016             case GPOINTER:
13017                 if (GPTRSIZE > AOP_SIZE(right)) {
13018                   // assume __data pointer... THIS MIGHT BE WRONG!
13019                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13020                 } else {
13021                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13022                 }
13023               break;
13024               
13025             default:
13026                 /* this should never happen */
13027                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13028                        "got unknown pointer type");
13029                 exit(1);
13030             }
13031             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13032             goto release ;
13033         }
13034         
13035         
13036         assert( 0 );
13037         /* just copy the pointers */
13038         size = AOP_SIZE(result);
13039         offset = 0 ;
13040         while (size--) {
13041             pic16_aopPut(AOP(result),
13042                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13043                    offset);
13044             offset++;
13045         }
13046         goto release ;
13047     }
13048     
13049
13050
13051     /* so we now know that the size of destination is greater
13052     than the size of the source.
13053     Now, if the next iCode is an operator then we might be
13054     able to optimize the operation without performing a cast.
13055     */
13056     if(genMixedOperation(ic))
13057       goto release;
13058
13059     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13060     
13061     /* we move to result for the size of source */
13062     size = AOP_SIZE(right);
13063     offset = 0 ;
13064
13065     while (size--) {
13066       if(!_G.resDirect)
13067         pic16_mov2f(AOP(result), AOP(right), offset);
13068       offset++;
13069     }
13070
13071     /* now depending on the sign of the destination */
13072     size = AOP_SIZE(result) - AOP_SIZE(right);
13073     /* if unsigned or not an integral type */
13074     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13075       while (size--)
13076         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13077     } else {
13078       /* we need to extend the sign :( */
13079
13080       if(size == 1) {
13081         /* Save one instruction of casting char to int */
13082         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13083         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13084         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13085       } else {
13086         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13087
13088         if(offset)
13089           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13090         else
13091           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13092         
13093         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13094
13095         while (size--)
13096           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13097       }
13098     }
13099
13100 release:
13101     pic16_freeAsmop(right,NULL,ic,TRUE);
13102     pic16_freeAsmop(result,NULL,ic,TRUE);
13103
13104 }
13105
13106 /*-----------------------------------------------------------------*/
13107 /* genDjnz - generate decrement & jump if not zero instrucion      */
13108 /*-----------------------------------------------------------------*/
13109 static int genDjnz (iCode *ic, iCode *ifx)
13110 {
13111     symbol *lbl, *lbl1;
13112     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13113
13114     if (!ifx)
13115         return 0;
13116     
13117     /* if the if condition has a false label
13118        then we cannot save */
13119     if (IC_FALSE(ifx))
13120         return 0;
13121
13122     /* if the minus is not of the form 
13123        a = a - 1 */
13124     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13125         !IS_OP_LITERAL(IC_RIGHT(ic)))
13126         return 0;
13127
13128     if (operandLitValue(IC_RIGHT(ic)) != 1)
13129         return 0;
13130
13131     /* if the size of this greater than one then no
13132        saving */
13133     if (getSize(operandType(IC_RESULT(ic))) > 1)
13134         return 0;
13135
13136     /* otherwise we can save BIG */
13137     lbl = newiTempLabel(NULL);
13138     lbl1= newiTempLabel(NULL);
13139
13140     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13141     
13142     if (IS_AOP_PREG(IC_RESULT(ic))) {
13143         pic16_emitcode("dec","%s",
13144                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13145         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13146         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13147     } else {    
13148
13149
13150       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13151       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13152
13153       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13154       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13155
13156     }
13157     
13158     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13159     ifx->generated = 1;
13160     return 1;
13161 }
13162
13163 /*-----------------------------------------------------------------*/
13164 /* genReceive - generate code for a receive iCode                  */
13165 /*-----------------------------------------------------------------*/
13166 static void genReceive (iCode *ic)
13167 {    
13168
13169   FENTRY;
13170
13171 #if 0
13172   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13173         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13174 #endif
13175 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13176
13177   if (isOperandInFarSpace(IC_RESULT(ic))
13178       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13179           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13180
13181     int size = getSize(operandType(IC_RESULT(ic)));
13182     int offset =  pic16_fReturnSizePic - size;
13183
13184       assert( 0 );
13185       while (size--) {
13186         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13187                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13188                       offset++;
13189         }
13190
13191       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13192
13193       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13194       size = AOP_SIZE(IC_RESULT(ic));
13195       offset = 0;
13196       while (size--) {
13197         pic16_emitcode ("pop","acc");
13198         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13199       }
13200   } else {
13201     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13202     _G.accInUse++;
13203     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13204     _G.accInUse--;
13205
13206     /* set pseudo stack pointer to where it should be - dw*/
13207     GpsuedoStkPtr = ic->parmBytes;
13208
13209     /* setting GpsuedoStkPtr has side effects here: */
13210     assignResultValue(IC_RESULT(ic), 0);
13211   }
13212
13213   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13214 }
13215
13216 /*-----------------------------------------------------------------*/
13217 /* genDummyRead - generate code for dummy read of volatiles        */
13218 /*-----------------------------------------------------------------*/
13219 static void
13220 genDummyRead (iCode * ic)
13221 {
13222   operand *op;
13223   int i;
13224
13225   op = IC_RIGHT(ic);
13226   if (op && IS_SYMOP(op)) {
13227     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13228       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13229       return;
13230     }
13231     pic16_aopOp (op, ic, FALSE);
13232     for (i=0; i < AOP_SIZE(op); i++) {
13233       // may need to protect this from the peepholer -- this is not nice but works...
13234       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13235       pic16_mov2w (AOP(op),i);
13236       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13237     } // for i
13238     pic16_freeAsmop (op, NULL, ic, TRUE);
13239   } else if (op) {
13240     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13241   } // if
13242 }
13243
13244 /*-----------------------------------------------------------------*/
13245 /* genpic16Code - generate code for pic16 based controllers        */
13246 /*-----------------------------------------------------------------*/
13247 /*
13248  * At this point, ralloc.c has gone through the iCode and attempted
13249  * to optimize in a way suitable for a PIC. Now we've got to generate
13250  * PIC instructions that correspond to the iCode.
13251  *
13252  * Once the instructions are generated, we'll pass through both the
13253  * peep hole optimizer and the pCode optimizer.
13254  *-----------------------------------------------------------------*/
13255
13256 void genpic16Code (iCode *lic)
13257 {
13258   iCode *ic;
13259   int cln = 0;
13260
13261     lineHead = lineCurr = NULL;
13262
13263     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13264     pic16_addpBlock(pb);
13265
13266 #if 0
13267     /* if debug information required */
13268     if (options.debug && currFunc) {
13269       if (currFunc) {
13270         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13271       }
13272     }
13273 #endif
13274
13275     for (ic = lic ; ic ; ic = ic->next ) {
13276
13277       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13278       if ( cln != ic->lineno ) {
13279         if ( options.debug ) {
13280           debugFile->writeCLine (ic);
13281         }
13282         
13283         if(!options.noCcodeInAsm) {
13284           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13285               printCLine(ic->filename, ic->lineno)));
13286         }
13287
13288         cln = ic->lineno ;
13289       }
13290         
13291       if(options.iCodeInAsm) {
13292         char *l;
13293
13294           /* insert here code to print iCode as comment */
13295           l = Safe_strdup(printILine(ic));
13296           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13297       }
13298
13299       /* if the result is marked as
13300        * spilt and rematerializable or code for
13301        * this has already been generated then
13302        * do nothing */
13303       if (resultRemat(ic) || ic->generated ) 
13304         continue ;
13305         
13306       /* depending on the operation */
13307       switch (ic->op) {
13308         case '!' :
13309           pic16_genNot(ic);
13310           break;
13311             
13312         case '~' :
13313           pic16_genCpl(ic);
13314           break;
13315             
13316         case UNARYMINUS:
13317           genUminus (ic);
13318           break;
13319             
13320         case IPUSH:
13321           genIpush (ic);
13322           break;
13323             
13324         case IPOP:
13325           /* IPOP happens only when trying to restore a 
13326            * spilt live range, if there is an ifx statement
13327            * following this pop then the if statement might
13328            * be using some of the registers being popped which
13329            * would destroy the contents of the register so
13330            * we need to check for this condition and handle it */
13331            if (ic->next
13332              && ic->next->op == IFX
13333              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13334                genIfx (ic->next,ic);
13335           else
13336             genIpop (ic);
13337           break; 
13338             
13339         case CALL:
13340           genCall (ic);
13341           break;
13342             
13343         case PCALL:
13344           genPcall (ic);
13345           break;
13346             
13347         case FUNCTION:
13348           genFunction (ic);
13349           break;
13350             
13351         case ENDFUNCTION:
13352           genEndFunction (ic);
13353           break;
13354             
13355         case RETURN:
13356           genRet (ic);
13357           break;
13358             
13359         case LABEL:
13360           genLabel (ic);
13361           break;
13362             
13363         case GOTO:
13364           genGoto (ic);
13365           break;
13366             
13367         case '+' :
13368           pic16_genPlus (ic) ;
13369           break;
13370             
13371         case '-' :
13372           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13373             pic16_genMinus (ic);
13374           break;
13375
13376         case '*' :
13377           genMult (ic);
13378           break;
13379             
13380         case '/' :
13381           genDiv (ic) ;
13382           break;
13383             
13384         case '%' :
13385           genMod (ic);
13386           break;
13387             
13388         case '>' :
13389           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13390           break;
13391             
13392         case '<' :
13393           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13394           break;
13395             
13396         case LE_OP:
13397         case GE_OP:
13398         case NE_OP:
13399           /* note these two are xlated by algebraic equivalence
13400            * during parsing SDCC.y */
13401           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13402             "got '>=' or '<=' shouldn't have come here");
13403           break;
13404
13405         case EQ_OP:
13406           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13407           break;            
13408             
13409         case AND_OP:
13410           genAndOp (ic);
13411           break;
13412             
13413         case OR_OP:
13414           genOrOp (ic);
13415           break;
13416             
13417         case '^' :
13418           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13419           break;
13420             
13421         case '|' :
13422           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13423           break;
13424             
13425         case BITWISEAND:
13426           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13427           break;
13428             
13429         case INLINEASM:
13430           genInline (ic);
13431           break;
13432             
13433         case RRC:
13434           genRRC (ic);
13435           break;
13436             
13437         case RLC:
13438           genRLC (ic);
13439           break;
13440             
13441         case GETHBIT:
13442           genGetHbit (ic);
13443           break;
13444             
13445         case LEFT_OP:
13446           genLeftShift (ic);
13447           break;
13448             
13449         case RIGHT_OP:
13450           genRightShift (ic);
13451           break;
13452             
13453         case GET_VALUE_AT_ADDRESS:
13454           genPointerGet(ic);
13455           break;
13456             
13457         case '=' :
13458           if (POINTER_SET(ic))
13459             genPointerSet(ic);
13460           else
13461             genAssign(ic);
13462           break;
13463             
13464         case IFX:
13465           genIfx (ic,NULL);
13466           break;
13467             
13468         case ADDRESS_OF:
13469           genAddrOf (ic);
13470           break;
13471             
13472         case JUMPTABLE:
13473           genJumpTab (ic);
13474           break;
13475             
13476         case CAST:
13477           genCast (ic);
13478           break;
13479             
13480         case RECEIVE:
13481           genReceive(ic);
13482           break;
13483             
13484         case SEND:
13485           addSet(&_G.sendSet,ic);
13486           break;
13487
13488         case DUMMY_READ_VOLATILE:
13489           genDummyRead (ic);
13490           break;
13491
13492         default :
13493           ic = ic;
13494       }
13495     }
13496
13497
13498     /* now we are ready to call the
13499        peep hole optimizer */
13500     if (!options.nopeep)
13501       peepHole (&lineHead);
13502
13503     /* now do the actual printing */
13504     printLine (lineHead, codeOutFile);
13505
13506 #ifdef PCODE_DEBUG
13507     DFPRINTF((stderr,"printing pBlock\n\n"));
13508     pic16_printpBlock(stdout,pb);
13509 #endif
13510
13511     return;
13512 }
13513