]> git.gag.com Git - fw/sdcc/blob - src/pic16/gen.c
d184da35e12ef4ac0265d3bc1445c41cf61561fe
[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 "FSR2 + 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 = %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       //if (dname) 
1558       //    return aop->aopu.aop_reg[offset]->dname;
1559       //else
1560             return aop->aopu.aop_reg[offset]->name;
1561         
1562     case AOP_CRY:
1563       //pic16_emitcode(";","%d",__LINE__);
1564       return aop->aopu.aop_dir;
1565         
1566     case AOP_ACC:
1567         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1568 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1569 //        assert( 0 );
1570 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1571         rs = Safe_strdup("WREG");
1572         return (rs);
1573
1574     case AOP_LIT:
1575         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1576         rs = Safe_calloc(1,strlen(s)+1);
1577         strcpy(rs,s);   
1578         return rs;
1579         
1580     case AOP_STR:
1581         aop->coff = offset ;
1582
1583 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1584 //          dname)
1585 //          return "acc";
1586         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1587           aop->type = AOP_ACC;
1588           return Safe_strdup("WREG");
1589         }
1590         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1591         
1592         return aop->aopu.aop_str[offset];
1593         
1594     case AOP_PCODE:
1595       {
1596         pCodeOp *pcop = aop->aopu.pcop;
1597         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1598         if(pcop->name) {
1599           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1600           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1601           if (offset) {
1602             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1603           } else {
1604             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1605           }
1606         } else
1607           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1608
1609       }
1610       rs = Safe_calloc(1,strlen(s)+1);
1611       strcpy(rs,s);   
1612       return rs;
1613
1614 #if 0
1615     case AOP_PAGED:
1616       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1617       if (offset) {
1618         sprintf(s,"(%s + %d)",
1619                 aop->aopu.aop_dir,
1620                 offset);
1621       } else
1622             sprintf(s,"%s",aop->aopu.aop_dir);
1623       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1624       rs = Safe_calloc(1,strlen(s)+1);
1625       strcpy(rs,s);   
1626       return rs;
1627 #endif
1628
1629     case AOP_STA:
1630         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1631         return (rs);
1632         
1633     case AOP_STK:
1634 //        pCodeOp *pcop = aop->aop
1635         break;
1636
1637     }
1638
1639     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1640     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1641            "aopget got unsupported aop->type");
1642     exit(0);
1643 }
1644
1645
1646
1647 /* lock has the following meaning: When allocating temporary registers
1648  * for stack variables storage, the value of the temporary register is
1649  * saved on stack. Its value is restored at the end. This procedure is
1650  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1651  * a possibility that before a call to pic16_aopOp, a temporary register
1652  * is allocated for a while and it is freed after some time, this will
1653  * mess the stack and values will not be restored properly. So use lock=1
1654  * to allocate temporary registers used internally by the programmer, and
1655  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1656  * to inform the compiler developer about a possible bug. This is an internal
1657  * feature for developing the compiler -- VR */
1658  
1659 int _TempReg_lock = 0;
1660 /*-----------------------------------------------------------------*/
1661 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1662 /*-----------------------------------------------------------------*/
1663 pCodeOp *pic16_popGetTempReg(int lock)
1664 {
1665   pCodeOp *pcop;
1666   symbol *cfunc;
1667
1668 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1669     if(_TempReg_lock) {
1670 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1671     }
1672     
1673     _TempReg_lock += lock;
1674     
1675     cfunc = currFunc;
1676     currFunc = NULL;
1677
1678     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1679     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1680       PCOR(pcop)->r->wasUsed=1;
1681       PCOR(pcop)->r->isFree=0;
1682
1683       /* push value on stack */
1684       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1685     }
1686
1687     currFunc = cfunc;
1688
1689   return pcop;
1690 }
1691
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1694 /*                           is not part of f, but don't save if   */
1695 /*                           inside v                              */
1696 /*-----------------------------------------------------------------*/
1697 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1698 {
1699   pCodeOp *pcop=NULL;
1700   symbol *cfunc;
1701   int i;
1702
1703 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1704
1705     if(_TempReg_lock) {
1706 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1707     }
1708
1709     _TempReg_lock += lock;
1710
1711     cfunc = currFunc;
1712     currFunc = NULL;
1713
1714     i = bitVectFirstBit(f);
1715     while(i < 128) {
1716
1717       /* bypass registers that are used by function */
1718       if(!bitVectBitValue(f, i)) {
1719       
1720         /* bypass registers that are already allocated for stack access */
1721         if(!bitVectBitValue(v, i))  {
1722         
1723 //          debugf("getting register rIdx = %d\n", i);
1724           /* ok, get the operand */
1725           pcop = pic16_newpCodeOpReg( i );
1726     
1727           /* should never by NULL */
1728           assert( pcop != NULL );
1729
1730           
1731           /* sanity check */
1732           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1733             int found=0;
1734             
1735               PCOR(pcop)->r->wasUsed=1;
1736               PCOR(pcop)->r->isFree=0;
1737
1738
1739               {
1740                 regs *sr;
1741               
1742                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1743
1744                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1745                       /* already used in previous steps, break */
1746                       found=1;          
1747                       break;
1748                     }
1749                   }
1750               }
1751
1752               /* caller takes care of the following */
1753 //              bitVectSetBit(v, i);
1754
1755               if(!found) {
1756                 /* push value on stack */
1757                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1758                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1759               }
1760           
1761             break;
1762           }
1763         }
1764       }
1765       i++;
1766     }
1767
1768     currFunc = cfunc;
1769
1770   return pcop;
1771 }
1772
1773
1774 /*-----------------------------------------------------------------*/
1775 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1776 /*-----------------------------------------------------------------*/
1777 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1778 {
1779   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1780
1781   _TempReg_lock -= lock;
1782
1783   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1784     PCOR(pcop)->r->isFree = 1;
1785
1786     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1787   }
1788 }
1789 /*-----------------------------------------------------------------*/
1790 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1791 /*-----------------------------------------------------------------*/
1792 pCodeOp *pic16_popGetLabel(unsigned int key)
1793 {
1794
1795   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1796
1797   if(key>max_key)
1798     max_key = key;
1799
1800   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1801 }
1802
1803 /*-----------------------------------------------------------------*/
1804 /* pic16_popCopyReg - copy a pcode operator                              */
1805 /*-----------------------------------------------------------------*/
1806 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1807 {
1808   pCodeOpReg *pcor;
1809
1810   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1811   memcpy (pcor, pc, sizeof (pCodeOpReg));
1812   pcor->r->wasUsed = 1;
1813   
1814   //pcor->pcop.type = pc->pcop.type;
1815   if(pc->pcop.name) {
1816     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1817       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1818   } else
1819     pcor->pcop.name = NULL;
1820
1821   //pcor->r = pc->r;
1822   //pcor->rIdx = pc->rIdx;
1823   //pcor->r->wasUsed=1;
1824   //pcor->instance = pc->instance;
1825
1826 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1827
1828   return PCOP(pcor);
1829 }
1830
1831 /*-----------------------------------------------------------------*/
1832 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1833 /*-----------------------------------------------------------------*/
1834 pCodeOp *pic16_popGetLit(int lit)
1835 {
1836   return pic16_newpCodeOpLit(lit);
1837 }
1838
1839 /*-----------------------------------------------------------------*/
1840 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1841 /*-----------------------------------------------------------------*/
1842 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1843 {
1844   return pic16_newpCodeOpLit2(lit, arg2);
1845 }
1846
1847
1848 /*-----------------------------------------------------------------*/
1849 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1850 /*-----------------------------------------------------------------*/
1851 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1852 {
1853   return pic16_newpCodeOpImmd(name, offset,index, 0);
1854 }
1855
1856
1857 /*-----------------------------------------------------------------*/
1858 /* pic16_popGet - asm operator to pcode operator conversion              */
1859 /*-----------------------------------------------------------------*/
1860 pCodeOp *pic16_popGetWithString(char *str)
1861 {
1862   pCodeOp *pcop;
1863
1864
1865   if(!str) {
1866     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1867     exit (1);
1868   }
1869
1870   pcop = pic16_newpCodeOp(str,PO_STR);
1871
1872   return pcop;
1873 }
1874
1875 /*-----------------------------------------------------------------*/
1876 /* pic16_popRegFromString -                                        */
1877 /*-----------------------------------------------------------------*/
1878 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1879 {
1880
1881   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1882   pcop->type = PO_DIR;
1883
1884   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1885   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1886
1887   if(!str)
1888     str = "BAD_STRING";
1889
1890   pcop->name = Safe_calloc(1,strlen(str)+1);
1891   strcpy(pcop->name,str);
1892
1893   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1894
1895   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1896
1897   /* make sure that register doesn't exist,
1898    * and operand isn't NULL
1899    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1900   if((PCOR(pcop)->r == NULL) 
1901     && (op)
1902     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1903 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1904 //              __FUNCTION__, __LINE__, str, size, offset);
1905
1906     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1907     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1908
1909   }
1910   PCOR(pcop)->instance = offset;
1911
1912   return pcop;
1913 }
1914
1915 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1916 {
1917   pCodeOp *pcop;
1918
1919 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1920
1921         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1922         PCOR(pcop)->rIdx = rIdx;
1923         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1924
1925         PCOR(pcop)->r->isFree = 0;
1926         PCOR(pcop)->r->wasUsed = 1;
1927
1928         pcop->type = PCOR(pcop)->r->pc_type;
1929
1930   return pcop;
1931 }
1932
1933 /*---------------------------------------------------------------------------------*/
1934 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1935 /*                 VR 030601                                                       */
1936 /*---------------------------------------------------------------------------------*/
1937 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1938 {
1939   pCodeOpReg2 *pcop2;
1940   pCodeOp *temp;
1941   
1942         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1943
1944         /* comment the following check, so errors to throw up */
1945 //      if(!pcop2)return NULL;
1946
1947         temp = pic16_popGet(aop_dst, offset);
1948         pcop2->pcop2 = temp;
1949         
1950   return PCOP(pcop2);
1951 }
1952
1953
1954
1955 /*--------------------------------------------------------------------------------.-*/
1956 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1957 /*                  VR 030601 , adapted by Hans Dorn                                */
1958 /*--------------------------------------------------------------------------------.-*/
1959 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1960 {
1961   pCodeOpReg2 *pcop2;
1962  
1963         pcop2 = (pCodeOpReg2 *)src;
1964         pcop2->pcop2 = dst;
1965         
1966         return PCOP(pcop2);
1967 }
1968
1969
1970
1971 /*---------------------------------------------------------------------------------*/
1972 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1973 /*                     movff instruction                                           */
1974 /*---------------------------------------------------------------------------------*/
1975 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1976 {
1977   pCodeOpReg2 *pcop2;
1978
1979         if(!noalloc) {
1980                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1981                 pcop2->pcop2 = pic16_popCopyReg(dst);
1982         } else {
1983                 /* the pCodeOp may be already allocated */
1984                 pcop2 = (pCodeOpReg2 *)(src);
1985                 pcop2->pcop2 = (pCodeOp *)(dst);
1986         }
1987
1988   return PCOP(pcop2);
1989 }
1990
1991
1992 /*-----------------------------------------------------------------*/
1993 /* pic16_popGet - asm operator to pcode operator conversion              */
1994 /*-----------------------------------------------------------------*/
1995 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1996 {
1997   //char *s = buffer ;
1998   char *rs;
1999   pCodeOp *pcop;
2000
2001     FENTRY2;
2002     /* offset is greater than
2003     size then zero */
2004
2005 //    if (offset > (aop->size - 1) &&
2006 //        aop->type != AOP_LIT)
2007 //      return NULL;  //zero;
2008
2009     /* depending on type */
2010     switch (aop->type) {
2011         
2012     case AOP_R0:
2013     case AOP_R1:
2014     case AOP_DPTR:
2015     case AOP_DPTR2:
2016         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2017         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2018         assert( 0 );
2019         return NULL;
2020
2021
2022     case AOP_FSR0:
2023     case AOP_FSR2:
2024       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2025       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2026       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2027       PCOR(pcop)->r->wasUsed = 1;
2028       PCOR(pcop)->r->isFree = 0;
2029       
2030       PCOR(pcop)->instance = offset;
2031       pcop->type = PCOR(pcop)->r->pc_type;
2032       return (pcop);
2033
2034     case AOP_IMMD:
2035       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2036       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2037
2038     case AOP_STA:
2039       /* pCodeOp is already allocated from aopForSym */
2040         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2041         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2042           
2043       return (pcop);
2044       
2045     case AOP_ACC:
2046       {
2047         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2048
2049         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2050
2051         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2052         
2053         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2054         PCOR(pcop)->rIdx = rIdx;
2055         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2056         PCOR(pcop)->r->wasUsed=1;
2057         PCOR(pcop)->r->isFree=0;
2058
2059         PCOR(pcop)->instance = offset;
2060         pcop->type = PCOR(pcop)->r->pc_type;
2061 //      rs = aop->aopu.aop_reg[offset]->name;
2062 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2063         return pcop;
2064
2065
2066 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2067 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2068
2069 //      assert( 0 );
2070       }
2071         
2072     case AOP_DIR:
2073       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2074       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2075         
2076 #if 0
2077     case AOP_PAGED:
2078       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2079       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2080 #endif
2081
2082     case AOP_REG:
2083       {
2084         int rIdx;
2085         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2086         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2087
2088         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2089         
2090         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2091 //      pcop->type = PO_GPR_REGISTER;
2092         PCOR(pcop)->rIdx = rIdx;
2093         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2094         PCOR(pcop)->r->wasUsed=1;
2095         PCOR(pcop)->r->isFree=0;
2096
2097         PCOR(pcop)->instance = offset;
2098         pcop->type = PCOR(pcop)->r->pc_type;
2099         
2100         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2101         rs = aop->aopu.aop_reg[offset]->name;
2102         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2103         return pcop;
2104       }
2105
2106     case AOP_CRY:
2107         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2108
2109       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2110       PCOR(pcop)->instance = offset;
2111       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2112       //if(PCOR(pcop)->r == NULL)
2113       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2114       return pcop;
2115         
2116     case AOP_LIT:
2117         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2118       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2119
2120     case AOP_STR:
2121       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2122       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2123
2124       /*
2125       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2126       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2127       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2128       pcop->type = PCOR(pcop)->r->pc_type;
2129       pcop->name = PCOR(pcop)->r->name;
2130
2131       return pcop;
2132       */
2133
2134     case AOP_PCODE:
2135       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2136                           __LINE__, 
2137                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2138       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2139       switch( aop->aopu.pcop->type ) {
2140         case PO_DIR: PCOR(pcop)->instance += offset; break;
2141         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2142         case PO_WREG:
2143             assert (offset==0);
2144             break;
2145         default:
2146           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2147           assert( 0 );  /* should never reach here */;
2148       }
2149       return pcop;
2150     }
2151
2152     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2153            "pic16_popGet got unsupported aop->type");
2154     exit(0);
2155 }
2156 /*-----------------------------------------------------------------*/
2157 /* pic16_aopPut - puts a string for a aop                                */
2158 /*-----------------------------------------------------------------*/
2159 void pic16_aopPut (asmop *aop, char *s, int offset)
2160 {
2161     char *d = buffer ;
2162     symbol *lbl ;
2163
2164     return;
2165
2166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2167
2168     if (aop->size && offset > ( aop->size - 1)) {
2169         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2170                "pic16_aopPut got offset > aop->size");
2171         exit(0);
2172     }
2173
2174     /* will assign value to value */
2175     /* depending on where it is ofcourse */
2176     switch (aop->type) {
2177     case AOP_DIR:
2178       if (offset) {
2179         sprintf(d,"(%s + %d)",
2180                 aop->aopu.aop_dir,offset);
2181         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2182
2183       } else
2184             sprintf(d,"%s",aop->aopu.aop_dir);
2185         
2186         if (strcmp(d,s)) {
2187           DEBUGpic16_emitcode(";","%d",__LINE__);
2188           if(strcmp(s,"W"))
2189             pic16_emitcode("movf","%s,w",s);
2190           pic16_emitcode("movwf","%s",d);
2191
2192           if(strcmp(s,"W")) {
2193             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2194             if(offset >= aop->size) {
2195               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2196               break;
2197             } else
2198               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2199           }
2200
2201           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2202
2203
2204         }
2205         break;
2206         
2207     case AOP_REG:
2208       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2209         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2210           /*
2211             if (*s == '@'           ||
2212                 strcmp(s,"r0") == 0 ||
2213                 strcmp(s,"r1") == 0 ||
2214                 strcmp(s,"r2") == 0 ||
2215                 strcmp(s,"r3") == 0 ||
2216                 strcmp(s,"r4") == 0 ||
2217                 strcmp(s,"r5") == 0 ||
2218                 strcmp(s,"r6") == 0 || 
2219                 strcmp(s,"r7") == 0 )
2220                 pic16_emitcode("mov","%s,%s  ; %d",
2221                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2222             else
2223           */
2224
2225           if(strcmp(s,"W")==0 )
2226             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2227
2228           pic16_emitcode("movwf","%s",
2229                    aop->aopu.aop_reg[offset]->name);
2230
2231           if(strcmp(s,zero)==0) {
2232             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2233
2234           } else if(strcmp(s,"W")==0) {
2235             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2236             pcop->type = PO_GPR_REGISTER;
2237
2238             PCOR(pcop)->rIdx = -1;
2239             PCOR(pcop)->r = NULL;
2240
2241             DEBUGpic16_emitcode(";","%d",__LINE__);
2242             pcop->name = Safe_strdup(s);
2243             pic16_emitpcode(POC_MOVFW,pcop);
2244             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2245           } else if(strcmp(s,one)==0) {
2246             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2247             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2248           } else {
2249             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2250           }
2251         }
2252         break;
2253         
2254     case AOP_DPTR:
2255     case AOP_DPTR2:
2256     
2257     if (aop->type == AOP_DPTR2)
2258     {
2259         genSetDPTR(1);
2260     }
2261     
2262         if (aop->code) {
2263             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2264                    "pic16_aopPut writting to code space");
2265             exit(0);
2266         }
2267         
2268         while (offset > aop->coff) {
2269             aop->coff++;
2270             pic16_emitcode ("inc","dptr");
2271         }
2272         
2273         while (offset < aop->coff) {
2274             aop->coff-- ;
2275             pic16_emitcode("lcall","__decdptr");
2276         }
2277         
2278         aop->coff = offset;
2279         
2280         /* if not in accumulater */
2281         MOVA(s);        
2282         
2283         pic16_emitcode ("movx","@dptr,a");
2284         
2285     if (aop->type == AOP_DPTR2)
2286     {
2287         genSetDPTR(0);
2288     }
2289         break;
2290         
2291     case AOP_R0:
2292     case AOP_R1:
2293         while (offset > aop->coff) {
2294             aop->coff++;
2295             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2296         }
2297         while (offset < aop->coff) {
2298             aop->coff-- ;
2299             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2300         }
2301         aop->coff = offset;
2302         
2303         if (aop->paged) {
2304             MOVA(s);           
2305             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2306             
2307         } else
2308             if (*s == '@') {
2309                 MOVA(s);
2310                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2311             } else
2312                 if (strcmp(s,"r0") == 0 ||
2313                     strcmp(s,"r1") == 0 ||
2314                     strcmp(s,"r2") == 0 ||
2315                     strcmp(s,"r3") == 0 ||
2316                     strcmp(s,"r4") == 0 ||
2317                     strcmp(s,"r5") == 0 ||
2318                     strcmp(s,"r6") == 0 || 
2319                     strcmp(s,"r7") == 0 ) {
2320                     char buffer[10];
2321                     sprintf(buffer,"a%s",s);
2322                     pic16_emitcode("mov","@%s,%s",
2323                              aop->aopu.aop_ptr->name,buffer);
2324                 } else
2325                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2326         
2327         break;
2328         
2329     case AOP_STK:
2330         if (strcmp(s,"a") == 0)
2331             pic16_emitcode("push","acc");
2332         else
2333             pic16_emitcode("push","%s",s);
2334         
2335         break;
2336         
2337     case AOP_CRY:
2338         /* if bit variable */
2339         if (!aop->aopu.aop_dir) {
2340             pic16_emitcode("clr","a");
2341             pic16_emitcode("rlc","a");
2342         } else {
2343             if (s == zero) 
2344                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2345             else
2346                 if (s == one)
2347                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2348                 else
2349                     if (!strcmp(s,"c"))
2350                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2351                     else {
2352                         lbl = newiTempLabel(NULL);
2353                         
2354                         if (strcmp(s,"a")) {
2355                             MOVA(s);
2356                         }
2357                         pic16_emitcode("clr","c");
2358                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2359                         pic16_emitcode("cpl","c");
2360                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2361                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2362                     }
2363         }
2364         break;
2365         
2366     case AOP_STR:
2367         aop->coff = offset;
2368         if (strcmp(aop->aopu.aop_str[offset],s))
2369             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2370         break;
2371         
2372     case AOP_ACC:
2373         aop->coff = offset;
2374         if (!offset && (strcmp(s,"acc") == 0))
2375             break;
2376         
2377         if (strcmp(aop->aopu.aop_str[offset],s))
2378             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2379         break;
2380
2381     default :
2382         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2383 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2384 //             "pic16_aopPut got unsupported aop->type");
2385 //      exit(0);    
2386     }    
2387
2388 }
2389
2390 /*-----------------------------------------------------------------*/
2391 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2392 /*-----------------------------------------------------------------*/
2393 void pic16_mov2w (asmop *aop, int offset)
2394 {
2395   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2396
2397   if(is_LitAOp(aop))
2398     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2399   else
2400     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2401 }
2402
2403 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2404 {
2405   if(is_LitAOp(src)) {
2406     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2407     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2408   } else {
2409     if(pic16_sameRegsOfs(src, dst, offset))return;
2410     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2411                       pic16_popGet(dst, offset)));
2412   }
2413 }
2414
2415 static void pic16_movLit2f(pCodeOp *pc, int lit)
2416 {
2417   if (0 == (lit & 0x00ff))
2418   {
2419     pic16_emitpcode (POC_CLRF, pc);
2420   } else if (0xff == (lit & 0x00ff))
2421   {
2422     pic16_emitpcode (POC_SETF, pc);
2423   } else {
2424     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2425     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2426   }
2427 }
2428
2429 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2430 {
2431   if(is_LitAOp(src)) {
2432     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2433     pic16_emitpcode(POC_MOVWF, dst);
2434   } else {
2435     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2436   }
2437 }
2438
2439 void pic16_testStackOverflow(void)
2440 {
2441 #define GSTACK_TEST_NAME        "_gstack_test"
2442
2443   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2444   
2445   {
2446     symbol *sym;
2447
2448       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2449       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2450 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2451       checkAddSym(&externs, sym);
2452   }
2453
2454 }
2455
2456 /* push pcop into stack */
2457 void pic16_pushpCodeOp(pCodeOp *pcop)
2458 {
2459 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2460   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2461   if(pic16_options.gstack)
2462     pic16_testStackOverflow();
2463     
2464 }
2465
2466 /* pop pcop from stack */
2467 void pic16_poppCodeOp(pCodeOp *pcop)
2468 {
2469   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2470   if(pic16_options.gstack)
2471     pic16_testStackOverflow();
2472 }
2473
2474
2475 /*-----------------------------------------------------------------*/
2476 /* pushw - pushes wreg to stack                                    */
2477 /*-----------------------------------------------------------------*/
2478 void pushw(void)
2479 {
2480   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2481   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2482   if(pic16_options.gstack)
2483     pic16_testStackOverflow();
2484 }
2485
2486                 
2487 /*-----------------------------------------------------------------*/
2488 /* pushaop - pushes aop to stack                                   */
2489 /*-----------------------------------------------------------------*/
2490 void pushaop(asmop *aop, int offset)
2491 {
2492   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493
2494   if(is_LitAOp(aop)) {
2495     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2496     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2497   } else {
2498     pic16_emitpcode(POC_MOVFF,
2499       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2500   }
2501
2502   if(pic16_options.gstack)
2503     pic16_testStackOverflow();
2504 }
2505
2506 /*-----------------------------------------------------------------*/
2507 /* popaop - pops aop from stack                                    */
2508 /*-----------------------------------------------------------------*/
2509 void popaop(asmop *aop, int offset)
2510 {
2511   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2512   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2513   if(pic16_options.gstack)
2514     pic16_testStackOverflow();
2515 }
2516
2517 void popaopidx(asmop *aop, int offset, int index)
2518 {
2519   int ofs=1;
2520
2521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2522
2523     if(STACK_MODEL_LARGE)ofs++;
2524
2525     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2526     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2527     if(pic16_options.gstack)
2528       pic16_testStackOverflow();
2529 }
2530
2531 #if !(USE_GENERIC_SIGNED_SHIFT)
2532 /*-----------------------------------------------------------------*/
2533 /* reAdjustPreg - points a register back to where it should        */
2534 /*-----------------------------------------------------------------*/
2535 static void reAdjustPreg (asmop *aop)
2536 {
2537     int size ;
2538
2539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2540     aop->coff = 0;
2541     if ((size = aop->size) <= 1)
2542         return ;
2543     size-- ;
2544     switch (aop->type) {
2545         case AOP_R0 :
2546         case AOP_R1 :
2547             while (size--)
2548                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2549             break;          
2550         case AOP_DPTR :
2551         case AOP_DPTR2:
2552             if (aop->type == AOP_DPTR2)
2553             {
2554                 genSetDPTR(1);
2555             } 
2556             while (size--)
2557             {
2558                 pic16_emitcode("lcall","__decdptr");
2559             }
2560                 
2561             if (aop->type == AOP_DPTR2)
2562             {
2563                 genSetDPTR(0);
2564             }                
2565             break;  
2566
2567     }   
2568
2569 }
2570 #endif
2571
2572 #if 0
2573 /*-----------------------------------------------------------------*/
2574 /* opIsGptr: returns non-zero if the passed operand is             */   
2575 /* a generic pointer type.                                         */
2576 /*-----------------------------------------------------------------*/ 
2577 static int opIsGptr(operand *op)
2578 {
2579     sym_link *type = operandType(op);
2580     
2581     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2582     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2583     {
2584         return 1;
2585     }
2586     return 0;        
2587 }
2588 #endif
2589
2590 /*-----------------------------------------------------------------*/
2591 /* pic16_getDataSize - get the operand data size                         */
2592 /*-----------------------------------------------------------------*/
2593 int pic16_getDataSize(operand *op)
2594 {
2595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2596
2597
2598     return AOP_SIZE(op);
2599
2600     // tsd- in the pic port, the genptr size is 1, so this code here
2601     // fails. ( in the 8051 port, the size was 4).
2602 #if 0
2603     int size;
2604     size = AOP_SIZE(op);
2605     if (size == GPTRSIZE)
2606     {
2607         sym_link *type = operandType(op);
2608         if (IS_GENPTR(type))
2609         {
2610             /* generic pointer; arithmetic operations
2611              * should ignore the high byte (pointer type).
2612              */
2613             size--;
2614     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2615         }
2616     }
2617     return size;
2618 #endif
2619 }
2620
2621 /*-----------------------------------------------------------------*/
2622 /* pic16_outAcc - output Acc                                             */
2623 /*-----------------------------------------------------------------*/
2624 void pic16_outAcc(operand *result)
2625 {
2626   int size,offset;
2627   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2628   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2629
2630
2631   size = pic16_getDataSize(result);
2632   if(size){
2633     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2634     size--;
2635     offset = 1;
2636     /* unsigned or positive */
2637     while(size--)
2638       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2639   }
2640
2641 }
2642
2643 /*-----------------------------------------------------------------*/
2644 /* pic16_outBitC - output a bit C                                  */
2645 /*                 Move to result the value of Carry flag -- VR    */
2646 /*-----------------------------------------------------------------*/
2647 void pic16_outBitC(operand *result)
2648 {
2649   int i;
2650
2651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2652
2653     /* if the result is bit */
2654     if (AOP_TYPE(result) == AOP_CRY) {
2655         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2656         pic16_aopPut(AOP(result),"c",0);
2657     } else {
2658
2659         i = AOP_SIZE(result);
2660         while(i--) {
2661                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2662         }
2663         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2664     }
2665 }
2666
2667 /*-----------------------------------------------------------------*/
2668 /* pic16_outBitOp - output a bit from Op                           */
2669 /*                 Move to result the value of set/clr op -- VR    */
2670 /*-----------------------------------------------------------------*/
2671 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2672 {
2673   int i;
2674
2675     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2676
2677     /* if the result is bit */
2678     if (AOP_TYPE(result) == AOP_CRY) {
2679         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2680         pic16_aopPut(AOP(result),"c",0);
2681     } else {
2682
2683         i = AOP_SIZE(result);
2684         while(i--) {
2685                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2686         }
2687         pic16_emitpcode(POC_RRCF, pcop);          
2688         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2689     }
2690 }
2691
2692 /*-----------------------------------------------------------------*/
2693 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2694 /*-----------------------------------------------------------------*/
2695 void pic16_toBoolean(operand *oper)
2696 {
2697     int size = AOP_SIZE(oper) - 1;
2698     int offset = 1;
2699
2700     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2701
2702     if ( AOP_TYPE(oper) != AOP_ACC) {
2703       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2704     }
2705     while (size--) {
2706       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2707     }
2708 }
2709
2710 /*-----------------------------------------------------------------*/
2711 /* genUminusFloat - unary minus for floating points                */
2712 /*-----------------------------------------------------------------*/
2713 static void genUminusFloat(operand *op,operand *result)
2714 {
2715   int size ,offset =0 ;
2716   
2717     FENTRY;
2718     /* for this we just need to flip the 
2719     first it then copy the rest in place */
2720     size = AOP_SIZE(op);
2721     assert( size == AOP_SIZE(result) );
2722
2723     while(size--) {
2724       pic16_mov2f(AOP(result), AOP(op), offset);
2725       offset++;
2726     }
2727     
2728     /* toggle the MSB's highest bit */
2729     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2730 }
2731
2732 /*-----------------------------------------------------------------*/
2733 /* genUminus - unary minus code generation                         */
2734 /*-----------------------------------------------------------------*/
2735 static void genUminus (iCode *ic)
2736 {
2737   int size, i;
2738   sym_link *optype, *rtype;
2739   symbol *label;
2740   int needLabel=0;
2741
2742     FENTRY;     
2743     
2744     /* assign asmops */
2745     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2746     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2747
2748     /* if both in bit space then special case */
2749     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2750       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2751         
2752         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2753         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2754         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2755         goto release; 
2756     } 
2757
2758     optype = operandType(IC_LEFT(ic));
2759     rtype = operandType(IC_RESULT(ic));
2760
2761
2762     /* if float then do float stuff */
2763     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2764       if(IS_FIXED(optype))
2765         debugf("implement fixed16x16 type\n", 0);
2766         
2767         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2768         goto release;
2769     }
2770
2771     /* otherwise subtract from zero by taking the 2's complement */
2772     size = AOP_SIZE(IC_LEFT(ic));
2773     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2774     label = newiTempLabel ( NULL );
2775     
2776     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2777       for (i=size-1; i > 0; i--) {
2778         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2779       } // for
2780       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2781       for (i=1; i < size; i++) {
2782         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2783         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2784       } // for
2785     } else {
2786       for (i=size-1; i >= 0; i--) {
2787         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2788         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2789       } // for
2790       if (size > 1) {
2791         for (i=0; i < size-2; i++) {
2792           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2793           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2794         } // for
2795         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2796       } // if
2797       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2798     }
2799     if (needLabel)
2800       pic16_emitpLabel (label->key);
2801
2802 release:
2803     /* release the aops */
2804     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2805     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2806 }
2807
2808 #if 0
2809 /*-----------------------------------------------------------------*/
2810 /* saveRegisters - will look for a call and save the registers     */
2811 /*-----------------------------------------------------------------*/
2812 static void saveRegisters(iCode *lic) 
2813 {
2814     int i;
2815     iCode *ic;
2816     bitVect *rsave;
2817     sym_link *dtype;
2818
2819     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2820     /* look for call */
2821     for (ic = lic ; ic ; ic = ic->next) 
2822         if (ic->op == CALL || ic->op == PCALL)
2823             break;
2824
2825     if (!ic) {
2826         fprintf(stderr,"found parameter push with no function call\n");
2827         return ;
2828     }
2829
2830     /* if the registers have been saved already then
2831     do nothing */
2832     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2833         return ;
2834
2835     /* find the registers in use at this time 
2836     and push them away to safety */
2837     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2838                           ic->rUsed);
2839
2840     ic->regsSaved = 1;
2841     if (options.useXstack) {
2842         if (bitVectBitValue(rsave,R0_IDX))
2843             pic16_emitcode("mov","b,r0");
2844         pic16_emitcode("mov","r0,%s",spname);
2845         for (i = 0 ; i < pic16_nRegs ; i++) {
2846             if (bitVectBitValue(rsave,i)) {
2847                 if (i == R0_IDX)
2848                     pic16_emitcode("mov","a,b");
2849                 else
2850                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2851                 pic16_emitcode("movx","@r0,a");
2852                 pic16_emitcode("inc","r0");
2853             }
2854         }
2855         pic16_emitcode("mov","%s,r0",spname);
2856         if (bitVectBitValue(rsave,R0_IDX))
2857             pic16_emitcode("mov","r0,b");           
2858     }// else
2859     //for (i = 0 ; i < pic16_nRegs ; i++) {
2860     //    if (bitVectBitValue(rsave,i))
2861     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2862     //}
2863
2864     dtype = operandType(IC_LEFT(ic));
2865     if (currFunc && dtype && 
2866         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2867         IFFUNC_ISISR(currFunc->type) &&
2868         !ic->bankSaved) 
2869
2870         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2871
2872 }
2873 /*-----------------------------------------------------------------*/
2874 /* unsaveRegisters - pop the pushed registers                      */
2875 /*-----------------------------------------------------------------*/
2876 static void unsaveRegisters (iCode *ic)
2877 {
2878     int i;
2879     bitVect *rsave;
2880
2881     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2882     /* find the registers in use at this time 
2883     and push them away to safety */
2884     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2885                           ic->rUsed);
2886     
2887     if (options.useXstack) {
2888         pic16_emitcode("mov","r0,%s",spname);   
2889         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2890             if (bitVectBitValue(rsave,i)) {
2891                 pic16_emitcode("dec","r0");
2892                 pic16_emitcode("movx","a,@r0");
2893                 if (i == R0_IDX)
2894                     pic16_emitcode("mov","b,a");
2895                 else
2896                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2897             }       
2898
2899         }
2900         pic16_emitcode("mov","%s,r0",spname);
2901         if (bitVectBitValue(rsave,R0_IDX))
2902             pic16_emitcode("mov","r0,b");
2903     } //else
2904     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2905     //    if (bitVectBitValue(rsave,i))
2906     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2907     //}
2908
2909 }  
2910 #endif
2911
2912 #if 0  // patch 14
2913 /*-----------------------------------------------------------------*/
2914 /* pushSide -                                                      */
2915 /*-----------------------------------------------------------------*/
2916 static void pushSide(operand * oper, int size)
2917 {
2918         int offset = 0;
2919     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2920         while (size--) {
2921                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2922                 if (AOP_TYPE(oper) != AOP_REG &&
2923                     AOP_TYPE(oper) != AOP_DIR &&
2924                     strcmp(l,"a") ) {
2925                         pic16_emitcode("mov","a,%s",l);
2926                         pic16_emitcode("push","acc");
2927                 } else
2928                         pic16_emitcode("push","%s",l);
2929         }
2930 }
2931 #endif // patch 14
2932
2933 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2934 {
2935   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2936     pic16_emitpcode(POC_MOVFW, src);
2937     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2938   } else {
2939     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2940         src, pic16_popGet(AOP(op), offset)));
2941   }
2942 }
2943
2944
2945 /*-----------------------------------------------------------------*/
2946 /* assignResultValue - assign results to oper, rescall==1 is       */
2947 /*                     called from genCall() or genPcall()         */
2948 /*-----------------------------------------------------------------*/
2949 static void assignResultValue(operand * oper, int rescall)
2950 {
2951   int size = AOP_SIZE(oper);
2952   int offset=0;
2953   
2954     FENTRY2;
2955 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2956     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2957
2958     if(rescall) {
2959       /* assign result from a call/pcall function() */
2960                 
2961       /* function results are stored in a special order,
2962        * see top of file with Function return policy, or manual */
2963
2964       if(size <= 4) {
2965         /* 8-bits, result in WREG */
2966         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2967                         
2968         if(size>1) {
2969           /* 16-bits, result in PRODL:WREG */
2970           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2971         }
2972                         
2973         if(size>2) {
2974           /* 24-bits, result in PRODH:PRODL:WREG */
2975           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2976         }
2977                         
2978         if(size>3) {
2979           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2980           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2981         }
2982       
2983       } else {
2984         /* >32-bits, result on stack, and FSR0 points to beginning.
2985          * Fix stack when done */
2986         /* FIXME FIXME */
2987 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2988         while (size--) {
2989 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2990 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2991                 
2992           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2993           GpsuedoStkPtr++;
2994         }
2995                         
2996         /* fix stack */
2997         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2998         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2999         if(STACK_MODEL_LARGE) {
3000           emitSKPNC;
3001           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3002         }
3003       }                 
3004     } else {
3005       int areg = 0;             /* matching argument register */
3006       
3007 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3008       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3009
3010
3011       /* its called from genReceive (probably) -- VR */
3012       /* I hope this code will not be called from somewhere else in the future! 
3013        * We manually set the pseudo stack pointer in genReceive. - dw
3014        */
3015       if(!GpsuedoStkPtr && _G.useWreg) {
3016 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3017
3018         /* The last byte in the assignment is in W */
3019         if(areg <= GpsuedoStkPtr) {
3020           size--;
3021           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3022           offset++;
3023 //          debugf("receive from WREG\n", 0);
3024         }
3025         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3026       }
3027 //      GpsuedoStkPtr++;
3028       _G.stack_lat = AOP_SIZE(oper)-1;
3029
3030       while (size) {
3031         size--;
3032         GpsuedoStkPtr++;
3033         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3034 //        debugf("receive from STACK\n", 0);
3035         offset++;
3036       }
3037     }
3038 }
3039
3040
3041 /*-----------------------------------------------------------------*/
3042 /* genIpush - generate code for pushing this gets a little complex */
3043 /*-----------------------------------------------------------------*/
3044 static void genIpush (iCode *ic)
3045 {
3046 //  int size, offset=0;
3047
3048   FENTRY;
3049   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3050
3051   if(ic->parmPush) {
3052     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3053
3054     /* send to stack as normal */
3055     addSet(&_G.sendSet,ic);
3056 //    addSetHead(&_G.sendSet,ic);
3057     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3058   }
3059
3060         
3061 #if 0
3062     int size, offset = 0 ;
3063     char *l;
3064
3065
3066     /* if this is not a parm push : ie. it is spill push 
3067     and spill push is always done on the local stack */
3068     if (!ic->parmPush) {
3069
3070         /* and the item is spilt then do nothing */
3071         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3072             return ;
3073
3074         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3075         size = AOP_SIZE(IC_LEFT(ic));
3076         /* push it on the stack */
3077         while(size--) {
3078             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3079             if (*l == '#') {
3080                 MOVA(l);
3081                 l = "acc";
3082             }
3083             pic16_emitcode("push","%s",l);
3084         }
3085         return ;        
3086     }
3087
3088     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3089 #endif
3090 }
3091
3092 /*-----------------------------------------------------------------*/
3093 /* genIpop - recover the registers: can happen only for spilling   */
3094 /*-----------------------------------------------------------------*/
3095 static void genIpop (iCode *ic)
3096 {
3097   FENTRY;
3098   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3099 #if 0
3100     int size,offset ;
3101
3102
3103     /* if the temp was not pushed then */
3104     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3105         return ;
3106
3107     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3108     size = AOP_SIZE(IC_LEFT(ic));
3109     offset = (size-1);
3110     while (size--) 
3111         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3112                                    FALSE,TRUE));
3113
3114     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3115 #endif
3116 }
3117
3118 #if 0
3119 /*-----------------------------------------------------------------*/
3120 /* unsaverbank - restores the resgister bank from stack            */
3121 /*-----------------------------------------------------------------*/
3122 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3123 {
3124   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3125 #if 0
3126     int i;
3127     asmop *aop ;
3128     regs *r = NULL;
3129
3130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3131     if (popPsw) {
3132         if (options.useXstack) {
3133             aop = newAsmop(0);
3134             r = getFreePtr(ic,&aop,FALSE);
3135             
3136             
3137             pic16_emitcode("mov","%s,_spx",r->name);
3138             pic16_emitcode("movx","a,@%s",r->name);
3139             pic16_emitcode("mov","psw,a");
3140             pic16_emitcode("dec","%s",r->name);
3141             
3142         }else
3143             pic16_emitcode ("pop","psw");
3144     }
3145
3146     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3147         if (options.useXstack) {       
3148             pic16_emitcode("movx","a,@%s",r->name);
3149             //pic16_emitcode("mov","(%s+%d),a",
3150             //       regspic16[i].base,8*bank+regspic16[i].offset);
3151             pic16_emitcode("dec","%s",r->name);
3152
3153         } else 
3154           pic16_emitcode("pop",""); //"(%s+%d)",
3155         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3156     }
3157
3158     if (options.useXstack) {
3159
3160         pic16_emitcode("mov","_spx,%s",r->name);
3161         pic16_freeAsmop(NULL,aop,ic,TRUE);
3162
3163     }
3164 #endif 
3165 }
3166
3167 /*-----------------------------------------------------------------*/
3168 /* saverbank - saves an entire register bank on the stack          */
3169 /*-----------------------------------------------------------------*/
3170 static void saverbank (int bank, iCode *ic, bool pushPsw)
3171 {
3172   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3173 #if 0
3174     int i;
3175     asmop *aop ;
3176     regs *r = NULL;
3177
3178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3179     if (options.useXstack) {
3180
3181         aop = newAsmop(0);
3182         r = getFreePtr(ic,&aop,FALSE);  
3183         pic16_emitcode("mov","%s,_spx",r->name);
3184
3185     }
3186
3187     for (i = 0 ; i < pic16_nRegs ;i++) {
3188         if (options.useXstack) {
3189             pic16_emitcode("inc","%s",r->name);
3190             //pic16_emitcode("mov","a,(%s+%d)",
3191             //         regspic16[i].base,8*bank+regspic16[i].offset);
3192             pic16_emitcode("movx","@%s,a",r->name);           
3193         } else 
3194           pic16_emitcode("push","");// "(%s+%d)",
3195                      //regspic16[i].base,8*bank+regspic16[i].offset);
3196     }
3197     
3198     if (pushPsw) {
3199         if (options.useXstack) {
3200             pic16_emitcode("mov","a,psw");
3201             pic16_emitcode("movx","@%s,a",r->name);     
3202             pic16_emitcode("inc","%s",r->name);
3203             pic16_emitcode("mov","_spx,%s",r->name);       
3204             pic16_freeAsmop (NULL,aop,ic,TRUE);
3205             
3206         } else
3207             pic16_emitcode("push","psw");
3208         
3209         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3210     }
3211     ic->bankSaved = 1;
3212 #endif
3213 }
3214 #endif  /* 0 */
3215
3216
3217 static int wparamCmp(void *p1, void *p2)
3218 {
3219   return (!strcmp((char *)p1, (char *)p2));
3220 }
3221
3222 int inWparamList(char *s)
3223 {
3224   return isinSetWith(wparamList, s, wparamCmp);
3225
3226
3227
3228 /*-----------------------------------------------------------------*/
3229 /* genCall - generates a call statement                            */
3230 /*-----------------------------------------------------------------*/
3231 static void genCall (iCode *ic)
3232 {
3233   sym_link *ftype;   
3234   int stackParms=0;
3235   int use_wreg=0;
3236   int inwparam=0;
3237   char *fname;
3238   
3239     FENTRY;
3240
3241     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3242     /* if caller saves & we have not saved then */
3243 //    if (!ic->regsSaved)
3244 //      saveRegisters(ic);
3245
3246         /* initialise stackParms for IPUSH pushes */
3247 //      stackParms = psuedoStkPtr;
3248 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3249     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3250     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3251
3252 #if 0
3253     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3254 #endif
3255
3256     /* if send set is not empty the assign */
3257     if (_G.sendSet) {
3258       iCode *sic;
3259       int psuedoStkPtr=-1; 
3260       int firstTimeThruLoop = 1;
3261
3262
3263         /* reverse sendSet if function is not reentrant */
3264         if(!IFFUNC_ISREENT(ftype))
3265           _G.sendSet = reverseSet(_G.sendSet);
3266
3267         /* First figure how many parameters are getting passed */
3268         stackParms = 0;
3269         use_wreg = 0;
3270         
3271         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3272           int size;
3273 //          int offset = 0;
3274
3275             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3276             size = AOP_SIZE(IC_LEFT(sic));
3277
3278             stackParms += size;
3279
3280             /* pass the last byte through WREG */
3281             if(inwparam) {
3282
3283               while (size--) {
3284                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3285                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3286                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3287
3288                 if(!firstTimeThruLoop) {
3289                   /* If this is not the first time we've been through the loop
3290                    * then we need to save the parameter in a temporary
3291                    * register. The last byte of the last parameter is
3292                    * passed in W. */
3293
3294                   pushw();
3295 //                  --psuedoStkPtr;             // sanity check
3296                   use_wreg = 1;
3297                 }
3298                 
3299                 firstTimeThruLoop=0;
3300
3301                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3302
3303 //                offset++;
3304               }
3305             } else {
3306               /* all arguments are passed via stack */
3307               use_wreg = 0;
3308
3309               while (size--) {
3310                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3311                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3312                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3313
3314 //                pushaop(AOP(IC_LEFT(sic)), size);
3315                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3316
3317                 if(!_G.resDirect)
3318                   pushw();
3319               }
3320             }
3321
3322             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3323           }
3324
3325           if(inwparam) {
3326             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3327               pushw();  /* save last parameter to stack if functions has varargs */
3328               use_wreg = 0;
3329             } else
3330               use_wreg = 1;
3331           } else use_wreg = 0;
3332
3333           _G.stackRegSet = _G.sendSet;
3334           _G.sendSet = NULL;
3335     }
3336
3337     /* make the call */
3338     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3339
3340     GpsuedoStkPtr=0;
3341     
3342     /* if we need to assign a result value */
3343     if ((IS_ITEMP(IC_RESULT(ic))
3344           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3345               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3346         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3347
3348       _G.accInUse++;
3349       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3350       _G.accInUse--;
3351
3352       assignResultValue(IC_RESULT(ic), 1);
3353
3354       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3355                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3356                 
3357       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3358     }
3359
3360     if(!stackParms && ic->parmBytes) {
3361       stackParms = ic->parmBytes;
3362     }
3363       
3364     stackParms -= use_wreg;
3365     
3366     if(stackParms>0) {
3367       if(stackParms == 1) {
3368         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3369       } else {
3370         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3371         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3372       }
3373       if(STACK_MODEL_LARGE) {
3374         emitSKPNC;
3375         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3376       }
3377     }
3378
3379 #if 0
3380     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3381 #endif
3382
3383     /* adjust the stack for parameters if required */
3384 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3385
3386 #if 0
3387       /* if register bank was saved then pop them */
3388       if (ic->bankSaved)
3389         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3390
3391       /* if we hade saved some registers then unsave them */
3392       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3393         unsaveRegisters (ic);
3394 #endif
3395 }
3396
3397
3398
3399 /*-----------------------------------------------------------------*/
3400 /* genPcall - generates a call by pointer statement                */
3401 /*            new version, created from genCall - HJD              */
3402 /*-----------------------------------------------------------------*/
3403 static void genPcall (iCode *ic)
3404 {
3405   sym_link *ftype, *fntype;
3406   int stackParms=0;
3407   symbol *retlbl = newiTempLabel(NULL);
3408   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3409   
3410     FENTRY;
3411
3412     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3413     fntype = operandType( IC_LEFT(ic) )->next;
3414
3415     /* if send set is not empty the assign */
3416     if (_G.sendSet) {
3417       iCode *sic;
3418       int psuedoStkPtr=-1; 
3419
3420       /* reverse sendSet if function is not reentrant */
3421       if(!IFFUNC_ISREENT(fntype))
3422         _G.sendSet = reverseSet(_G.sendSet);
3423
3424       stackParms = 0;
3425       
3426       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3427         int size;
3428
3429           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3430           size = AOP_SIZE(IC_LEFT(sic));
3431           stackParms += size;
3432
3433           /* all parameters are passed via stack, since WREG is clobbered
3434            * by the calling sequence */
3435           while (size--) {
3436             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3437             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3438             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3439
3440             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3441             pushw();
3442           }
3443
3444           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3445       }
3446
3447       _G.stackRegSet = _G.sendSet;
3448       _G.sendSet = NULL;
3449     }
3450
3451     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3452
3453     // push return address
3454     // push $ on return stack, then replace with retlbl
3455
3456     /* Thanks to Thorsten Klose for pointing out that the following
3457      * snippet should be interrupt safe */
3458     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3459     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3460
3461     pic16_emitpcodeNULLop(POC_PUSH);
3462
3463     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3464     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3465     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3466     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3467     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3468     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3469
3470
3471     /* restore interrupt control register */
3472     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3473     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3474
3475     /* make the call by writing the pointer into pc */
3476     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3477     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3478
3479     // note: MOVFF to PCL not allowed
3480     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3481     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3482
3483
3484     /* return address is here: (X) */
3485     pic16_emitpLabelFORCE(retlbl->key);
3486
3487     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3488
3489     GpsuedoStkPtr=0;
3490     /* if we need assign a result value */
3491     if ((IS_ITEMP(IC_RESULT(ic))
3492           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3493               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3494         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3495
3496       _G.accInUse++;
3497       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3498       _G.accInUse--;
3499
3500       assignResultValue(IC_RESULT(ic), 1);
3501
3502       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3503               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3504                 
3505       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3506     }
3507
3508 //    stackParms -= use_wreg;
3509     
3510     if(stackParms>0) {
3511       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3512       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3513       if(STACK_MODEL_LARGE) {
3514         emitSKPNC;
3515         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3516       }
3517     }
3518 }
3519
3520 /*-----------------------------------------------------------------*/
3521 /* resultRemat - result  is rematerializable                       */
3522 /*-----------------------------------------------------------------*/
3523 static int resultRemat (iCode *ic)
3524 {
3525   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3526   if (SKIP_IC(ic) || ic->op == IFX)
3527     return 0;
3528
3529   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3530     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3531     if (sym->remat && !POINTER_SET(ic)) 
3532       return 1;
3533   }
3534
3535   return 0;
3536 }
3537
3538 #if defined(__BORLANDC__) || defined(_MSC_VER)
3539 #define STRCASECMP stricmp
3540 #else
3541 #define STRCASECMP strcasecmp
3542 #endif
3543
3544 #if 0
3545 /*-----------------------------------------------------------------*/
3546 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3547 /*-----------------------------------------------------------------*/
3548 static bool inExcludeList(char *s)
3549 {
3550   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3551     int i =0;
3552     
3553     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3554     if (options.excludeRegs[i] &&
3555     STRCASECMP(options.excludeRegs[i],"none") == 0)
3556         return FALSE ;
3557
3558     for ( i = 0 ; options.excludeRegs[i]; i++) {
3559         if (options.excludeRegs[i] &&
3560         STRCASECMP(s,options.excludeRegs[i]) == 0)
3561             return TRUE;
3562     }
3563     return FALSE ;
3564 }
3565 #endif
3566
3567 /*-----------------------------------------------------------------*/
3568 /* genFunction - generated code for function entry                 */
3569 /*-----------------------------------------------------------------*/
3570 static void genFunction (iCode *ic)
3571 {
3572   symbol *sym;
3573   sym_link *ftype;
3574   
3575     FENTRY;
3576     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3577
3578     pic16_labelOffset += (max_key+4);
3579     max_key=0;
3580     GpsuedoStkPtr=0;
3581     _G.nRegsSaved = 0;
3582         
3583     ftype = operandType(IC_LEFT(ic));
3584     sym = OP_SYMBOL(IC_LEFT(ic));
3585
3586     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3587       /* create an absolute section at the interrupt vector:
3588        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3589       symbol *asym;
3590       char asymname[128];
3591       pBlock *apb;
3592
3593 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3594
3595         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3596           sprintf(asymname, "ivec_%s", sym->name);
3597         else
3598           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3599   
3600         /* when an interrupt is declared as naked, do not emit the special
3601          * wrapper segment at vector address. The user should take care for
3602          * this instead. -- VR */
3603
3604         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3605           asym = newSymbol(asymname, 0);
3606           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3607           pic16_addpBlock( apb );
3608
3609           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3610           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3611           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3612           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3613           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3614                 
3615           /* mark the end of this tiny function */
3616           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3617         } else {
3618           sprintf(asymname, "%s", sym->rname);
3619         }
3620
3621         {
3622           absSym *abSym;
3623
3624             abSym = Safe_calloc(1, sizeof(absSym));
3625             strcpy(abSym->name, asymname);
3626
3627             switch( FUNC_INTNO(sym->type) ) {
3628               case 0: abSym->address = 0x000000; break;
3629               case 1: abSym->address = 0x000008; break;
3630               case 2: abSym->address = 0x000018; break;
3631               
3632               default:
3633 //                fprintf(stderr, "no interrupt number is given\n");
3634                 abSym->address = -1; break;
3635             }
3636
3637             /* relocate interrupt vectors if needed */
3638             if(abSym->address != -1)
3639               abSym->address += pic16_options.ivt_loc;
3640
3641             addSet(&absSymSet, abSym);
3642         }
3643     }
3644
3645     /* create the function header */
3646     pic16_emitcode(";","-----------------------------------------");
3647     pic16_emitcode(";"," function %s",sym->name);
3648     pic16_emitcode(";","-----------------------------------------");
3649
3650     pic16_emitcode("","%s:",sym->rname);
3651     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3652
3653     {
3654       absSym *ab;
3655
3656         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3657           if(!strcmp(ab->name, sym->rname)) {
3658             pic16_pBlockConvert2Absolute(pb);
3659             break;
3660           }
3661         }
3662     }
3663
3664     if(IFFUNC_ISNAKED(ftype)) {
3665       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3666       return;
3667     }
3668         
3669     /* if critical function then turn interrupts off */
3670     if (IFFUNC_ISCRITICAL(ftype)) {
3671       //pic16_emitcode("clr","ea");
3672     }
3673
3674     currFunc = sym;             /* update the currFunc symbol */
3675     _G.fregsUsed = sym->regsUsed;
3676     _G.sregsAlloc = newBitVect(128);
3677     
3678
3679     /* if this is an interrupt service routine then
3680      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3681     if (IFFUNC_ISISR(sym->type)) {
3682         _G.usefastretfie = 1;   /* use shadow registers by default */
3683         
3684         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3685         if(!FUNC_ISSHADOWREGS(sym->type)) {
3686           /* do not save WREG,STATUS,BSR for high priority interrupts
3687            * because they are stored in the hardware shadow registers already */
3688           _G.usefastretfie = 0;
3689           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3690           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3691           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3692         }
3693
3694         /* these should really be optimized somehow, because not all
3695          * interrupt handlers modify them */
3696         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3697         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3698         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3699         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3700         
3701 //        pic16_pBlockConvert2ISR(pb);
3702     }
3703
3704     /* emit code to setup stack frame if user enabled,
3705      * and function is not main() */
3706     
3707 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3708     if(strcmp(sym->name, "main")) {
3709       if(0 
3710         || !options.ommitFramePtr 
3711 //        || sym->regsUsed
3712         || IFFUNC_ARGS(sym->type)
3713         || FUNC_HASSTACKPARM(sym->etype)
3714         ) {
3715         /* setup the stack frame */
3716         if(STACK_MODEL_LARGE)
3717           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3718         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3719
3720         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3721         if(STACK_MODEL_LARGE)
3722           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3723       }
3724     }
3725
3726     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3727           && sym->stack) {
3728
3729       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3730
3731       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3732       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3733       emitSKPC;
3734       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3735     }
3736           
3737     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3738       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3739         _G.useWreg = 0;
3740       else
3741         _G.useWreg = 1;
3742     } else
3743       _G.useWreg = 0;
3744
3745     /* if callee-save to be used for this function
3746      * then save the registers being used in this function */
3747 //    if (IFFUNC_CALLEESAVES(sym->type))
3748     {
3749       int i;
3750
3751         /* if any registers used */
3752         if (sym->regsUsed) {
3753           /* save the registers used */
3754           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3755           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3756           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3757             if (bitVectBitValue(sym->regsUsed,i)) {
3758               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3759               _G.nRegsSaved++;
3760
3761               if(!pic16_regWithIdx(i)->wasUsed) {
3762                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3763                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3764                 pic16_regWithIdx(i)->wasUsed = 1;
3765               }
3766             }
3767           }
3768           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3769         }
3770     }
3771         
3772     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3773 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3774 }
3775
3776 /*-----------------------------------------------------------------*/
3777 /* genEndFunction - generates epilogue for functions               */
3778 /*-----------------------------------------------------------------*/
3779 static void genEndFunction (iCode *ic)
3780 {
3781   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3782
3783     FENTRY;
3784
3785     if(IFFUNC_ISNAKED(sym->type)) {
3786       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3787       return;
3788     }
3789
3790     _G.stack_lat = 0;
3791
3792     /* add code for ISCRITICAL */
3793     if(IFFUNC_ISCRITICAL(sym->type)) {
3794       /* if critical function, turn on interrupts */
3795       
3796       /* TODO: add code here -- VR */
3797     }
3798     
3799 //    sym->regsUsed = _G.fregsUsed;
3800     
3801     /* now we need to restore the registers */
3802     /* if any registers used */
3803
3804     /* first restore registers that might be used for stack access */
3805     if(_G.sregsAllocSet) {
3806     regs *sr;
3807     
3808       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3809       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3810         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3811       }
3812     }
3813
3814     if (sym->regsUsed) {
3815       int i;
3816
3817         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3818         /* restore registers used */
3819         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3820         for ( i = sym->regsUsed->size; i >= 0; i--) {
3821           if (bitVectBitValue(sym->regsUsed,i)) {
3822             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3823             _G.nRegsSaved--;
3824           }
3825         }
3826         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3827     }
3828
3829       
3830
3831     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3832           && sym->stack) {
3833       if (sym->stack == 1) {
3834         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3835         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3836       } else {
3837         // we have to add more than one...
3838         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3839         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3840         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3841         emitSKPNC;
3842         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3843         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3844         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3845       }
3846     }
3847
3848     if(strcmp(sym->name, "main")) {
3849       if(0
3850         || !options.ommitFramePtr
3851 //        || sym->regsUsed
3852         || IFFUNC_ARGS(sym->type)
3853         || FUNC_HASSTACKPARM(sym->etype)
3854         ) {
3855         /* restore stack frame */
3856         if(STACK_MODEL_LARGE)
3857           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3858         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3859       }
3860     }
3861
3862     _G.useWreg = 0;
3863
3864     if (IFFUNC_ISISR(sym->type)) {
3865       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3866       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3867       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3868       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3869
3870       if(!FUNC_ISSHADOWREGS(sym->type)) {
3871         /* do not restore interrupt vector for WREG,STATUS,BSR
3872          * for high priority interrupt, see genFunction */
3873         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3874         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3875         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3876       }
3877 //      _G.interruptvector = 0;         /* sanity check */
3878
3879
3880       /* if debug then send end of function */
3881 /*      if (options.debug && currFunc)  */
3882       if (currFunc) {
3883         debugFile->writeEndFunction (currFunc, ic, 1);
3884       }
3885         
3886       if(_G.usefastretfie)
3887         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3888       else
3889         pic16_emitpcodeNULLop(POC_RETFIE);
3890
3891       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3892       
3893       _G.usefastretfie = 0;
3894       return;
3895     }
3896
3897     if (IFFUNC_ISCRITICAL(sym->type)) {
3898       pic16_emitcode("setb","ea");
3899     }
3900
3901     /* if debug then send end of function */
3902     if (currFunc) {
3903       debugFile->writeEndFunction (currFunc, ic, 1);
3904     }
3905
3906     /* insert code to restore stack frame, if user enabled it
3907      * and function is not main() */
3908          
3909
3910     pic16_emitpcodeNULLop(POC_RETURN);
3911
3912     /* Mark the end of a function */
3913     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3914 }
3915
3916
3917 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3918 {
3919   unsigned long lit=1;
3920   operand *op;
3921
3922     op = IC_LEFT(ic);
3923   
3924     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3925     if(AOP_TYPE(op) == AOP_LIT) {
3926       if(!IS_FLOAT(operandType( op ))) {
3927         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3928       } else {
3929         union {
3930           unsigned long lit_int;
3931           float lit_float;
3932         } info;
3933         
3934         /* take care if literal is a float */
3935         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3936         lit = info.lit_int;
3937       }
3938     }
3939
3940     if(is_LitOp(op)) {
3941       pic16_movLit2f(dest, lit);
3942     } else {
3943       if(dest->type == PO_WREG && (offset == 0)) {
3944         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3945       return;
3946     }
3947     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3948   }
3949 }
3950
3951 /*-----------------------------------------------------------------*/
3952 /* genRet - generate code for return statement                     */
3953 /*-----------------------------------------------------------------*/
3954 static void genRet (iCode *ic)
3955 {
3956   int size;
3957   operand *left;
3958
3959     FENTRY;
3960         /* if we have no return value then
3961          * just generate the "ret" */
3962         
3963         if (!IC_LEFT(ic)) 
3964                 goto jumpret;       
3965     
3966         /* we have something to return then
3967          * move the return value into place */
3968         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3969         size = AOP_SIZE(IC_LEFT(ic));
3970
3971         if(size <= 4) {
3972           if(size>3)
3973             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3974           
3975           if(size>2)
3976             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3977
3978           if(size>1)
3979             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3980           
3981           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3982
3983         } else {
3984                 /* >32-bits, setup stack and FSR0 */
3985                 while (size--) {
3986 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3987 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3988
3989                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3990
3991 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3992                         GpsuedoStkPtr++;
3993                 }
3994                         
3995                 /* setup FSR0 */
3996                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3997                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3998
3999                 if(STACK_MODEL_LARGE) {
4000                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4001                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4002                 } else {
4003                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4004                 }
4005         }
4006                                 
4007 #if 0
4008         /* old code, left here for reference -- VR */    
4009         while (size--) {
4010           char *l ;
4011
4012                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4013                         /* #NOCHANGE */
4014                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4015                         pic16_emitpcomment("push %s",l);
4016                         pushed++;
4017                 } else {
4018                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4019                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4020                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4021                         
4022                         if (strcmp(fReturn[offset],l)) {
4023                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4024                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4025                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4026                                 } else {
4027                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4028                                 }
4029                                 
4030                                 if(size) {
4031                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4032                                 }
4033                                 offset++;
4034                         }
4035                 }
4036         }    
4037
4038         if (pushed) {
4039                 while(pushed) {
4040                         pushed--;
4041                         if (strcmp(fReturn[pushed],"a"))
4042                                 pic16_emitcode("pop",fReturn[pushed]);
4043                         else
4044                                 pic16_emitcode("pop","acc");
4045                 }
4046         }
4047 #endif
4048
4049
4050         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4051     
4052 jumpret:
4053         /* generate a jump to the return label
4054          * if the next is not the return statement */
4055         if (!(ic->next && ic->next->op == LABEL
4056                 && IC_LABEL(ic->next) == returnLabel)) {
4057         
4058                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4059                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4060         }
4061 }
4062
4063 /*-----------------------------------------------------------------*/
4064 /* genLabel - generates a label                                    */
4065 /*-----------------------------------------------------------------*/
4066 static void genLabel (iCode *ic)
4067 {
4068   FENTRY;
4069
4070   /* special case never generate */
4071   if (IC_LABEL(ic) == entryLabel)
4072     return ;
4073
4074   pic16_emitpLabel(IC_LABEL(ic)->key);
4075 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4076 }
4077
4078 /*-----------------------------------------------------------------*/
4079 /* genGoto - generates a goto                                      */
4080 /*-----------------------------------------------------------------*/
4081 //tsd
4082 static void genGoto (iCode *ic)
4083 {
4084   FENTRY;
4085   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4086 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4087 }
4088
4089
4090 /*-----------------------------------------------------------------*/
4091 /* genMultbits :- multiplication of bits                           */
4092 /*-----------------------------------------------------------------*/
4093 static void genMultbits (operand *left, 
4094                          operand *right, 
4095                          operand *result)
4096 {
4097   FENTRY;
4098
4099   if(!pic16_sameRegs(AOP(result),AOP(right)))
4100     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4101
4102   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4103   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4104   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4105
4106 }
4107
4108
4109 /*-----------------------------------------------------------------*/
4110 /* genMultOneByte : 8 bit multiplication & division                */
4111 /*-----------------------------------------------------------------*/
4112 static void genMultOneByte (operand *left,
4113                             operand *right,
4114                             operand *result)
4115 {
4116
4117   FENTRY;
4118   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4119   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4120
4121   /* (if two literals, the value is computed before) */
4122   /* if one literal, literal on the right */
4123   if (AOP_TYPE(left) == AOP_LIT){
4124     operand *t = right;
4125     right = left;
4126     left = t;
4127   }
4128
4129         /* size is already checked in genMult == 1 */
4130 //      size = AOP_SIZE(result);
4131
4132         if (AOP_TYPE(right) == AOP_LIT){
4133                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4134                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4135                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4136                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4137         } else {
4138                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4139                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4140                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4141                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4142         }
4143         
4144         pic16_genMult8X8_8 (left, right,result);
4145 }
4146
4147 /*-----------------------------------------------------------------*/
4148 /* genMultOneWord : 16 bit multiplication                          */
4149 /*-----------------------------------------------------------------*/
4150 static void genMultOneWord (operand *left,
4151                             operand *right,
4152                             operand *result)
4153 {
4154   FENTRY;
4155   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4156   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4157
4158   /* (if two literals, the value is computed before)
4159    * if one literal, literal on the right */
4160   if (AOP_TYPE(left) == AOP_LIT){
4161     operand *t = right;
4162     right = left;
4163     left = t;
4164   }
4165
4166   /* size is checked already == 2 */
4167 //  size = AOP_SIZE(result);
4168
4169   if (AOP_TYPE(right) == AOP_LIT) {
4170     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4171       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4172       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4173       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4174   } else {
4175     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4176       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4177       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4178       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4179   }
4180         
4181   pic16_genMult16X16_16(left, right,result);
4182 }
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneLong : 32 bit multiplication                          */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneLong (operand *left,
4188                             operand *right,
4189                             operand *result)
4190 {
4191   FENTRY;
4192   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4193   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4194
4195   /* (if two literals, the value is computed before)
4196    * if one literal, literal on the right */
4197   if (AOP_TYPE(left) == AOP_LIT){
4198     operand *t = right;
4199     right = left;
4200     left = t;
4201   }
4202
4203   /* size is checked already == 4 */
4204 //  size = AOP_SIZE(result);
4205
4206   if (AOP_TYPE(right) == AOP_LIT) {
4207     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4208         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4209         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4210         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4211   } else {
4212     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4213         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4214         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4215         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4216   }
4217         
4218   pic16_genMult32X32_32(left, right,result);
4219 }
4220
4221
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genMult - generates code for multiplication                     */
4225 /*-----------------------------------------------------------------*/
4226 static void genMult (iCode *ic)
4227 {
4228   operand *left = IC_LEFT(ic);
4229   operand *right = IC_RIGHT(ic);
4230   operand *result= IC_RESULT(ic);   
4231
4232     FENTRY;
4233         /* assign the amsops */
4234         pic16_aopOp (left,ic,FALSE);
4235         pic16_aopOp (right,ic,FALSE);
4236         pic16_aopOp (result,ic,TRUE);
4237
4238         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4239
4240         /* special cases first *
4241         * both are bits */
4242         if (AOP_TYPE(left) == AOP_CRY
4243                 && AOP_TYPE(right)== AOP_CRY) {
4244                 genMultbits(left,right,result);
4245           goto release ;
4246         }
4247
4248         /* if both are of size == 1 */
4249         if(AOP_SIZE(left) == 1
4250                 && AOP_SIZE(right) == 1) {
4251                 genMultOneByte(left,right,result);
4252           goto release ;
4253         }
4254
4255         /* if both are of size == 2 */
4256         if(AOP_SIZE(left) == 2
4257                 && AOP_SIZE(right) == 2) {
4258                 genMultOneWord(left, right, result);
4259           goto release;
4260         }
4261         
4262         /* if both are of size == 4 */
4263         if(AOP_SIZE(left) == 4
4264                 && AOP_SIZE(right) == 4) {
4265                 genMultOneLong(left, right, result);
4266           goto release;
4267         }
4268         
4269         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4270
4271
4272         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4273         /* should have been converted to function call */
4274         assert(0) ;
4275
4276 release :
4277         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4279         pic16_freeAsmop(result,NULL,ic,TRUE); 
4280 }
4281
4282 /*-----------------------------------------------------------------*/
4283 /* genDivbits :- division of bits                                  */
4284 /*-----------------------------------------------------------------*/
4285 static void genDivbits (operand *left, 
4286                         operand *right, 
4287                         operand *result)
4288 {
4289   char *l;
4290
4291     FENTRY;
4292     /* the result must be bit */    
4293     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4294     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4295
4296     MOVA(l);    
4297
4298     pic16_emitcode("div","ab");
4299     pic16_emitcode("rrc","a");
4300     pic16_aopPut(AOP(result),"c",0);
4301 }
4302
4303 /*-----------------------------------------------------------------*/
4304 /* genDivOneByte : 8 bit division                                  */
4305 /*-----------------------------------------------------------------*/
4306 static void genDivOneByte (operand *left,
4307                            operand *right,
4308                            operand *result)
4309 {
4310   sym_link *opetype = operandType(result);
4311   char *l ;
4312   symbol *lbl ;
4313   int size,offset;
4314
4315         /* result = divident / divisor
4316          * - divident may be a register or a literal,
4317          * - divisor may be a register or a literal,
4318          * so there are 3 cases (literal / literal is optimized
4319          * by the front-end) to handle.
4320          * In addition we must handle signed and unsigned, which
4321          * result in 6 final different cases -- VR */
4322
4323     FENTRY;
4324     
4325     size = AOP_SIZE(result) - 1;
4326     offset = 1;
4327     /* signed or unsigned */
4328     if (SPEC_USIGN(opetype)) {
4329       pCodeOp *pct1,    /* count */
4330                 *pct2,  /* reste */
4331                 *pct3;  /* temp */
4332       symbol *label1, *label2, *label3;;
4333
4334
4335         /* unsigned is easy */
4336
4337         pct1 = pic16_popGetTempReg(1);
4338         pct2 = pic16_popGetTempReg(1);
4339         pct3 = pic16_popGetTempReg(1);
4340         
4341         label1 = newiTempLabel(NULL);
4342         label2 = newiTempLabel(NULL);
4343         label3 = newiTempLabel(NULL);
4344
4345         /* the following algorithm is extracted from divuint.c */
4346
4347         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4348         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4349         
4350         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4351
4352         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4353         
4354         pic16_emitpLabel(label1->key);
4355         
4356         emitCLRC;
4357         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4358
4359
4360         emitCLRC;
4361         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4362         
4363
4364         emitSKPNC;
4365         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4366         
4367         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4368         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4369         
4370         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4371         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4372         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4373         
4374         pic16_emitpLabel( label3->key );
4375         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4376         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4377         
4378         
4379
4380         pic16_emitpLabel(label2->key);
4381         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4382         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4383         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4384         
4385         /* result is in wreg */
4386         if(AOP_TYPE(result) != AOP_ACC)
4387                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4388
4389         pic16_popReleaseTempReg( pct3, 1);
4390         pic16_popReleaseTempReg( pct2, 1);
4391         pic16_popReleaseTempReg( pct1, 1);
4392
4393         return ;
4394     }
4395
4396     /* signed is a little bit more difficult */
4397
4398     /* save the signs of the operands */
4399     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4400     MOVA(l);    
4401     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4402     pic16_emitcode("push","acc"); /* save it on the stack */
4403
4404     /* now sign adjust for both left & right */
4405     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4406     MOVA(l);       
4407     lbl = newiTempLabel(NULL);
4408     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4409     pic16_emitcode("cpl","a");   
4410     pic16_emitcode("inc","a");
4411     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4412     pic16_emitcode("mov","b,a");
4413
4414     /* sign adjust left side */
4415     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4416     MOVA(l);
4417
4418     lbl = newiTempLabel(NULL);
4419     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4420     pic16_emitcode("cpl","a");
4421     pic16_emitcode("inc","a");
4422     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4423
4424     /* now the division */
4425     pic16_emitcode("div","ab");
4426     /* we are interested in the lower order
4427     only */
4428     pic16_emitcode("mov","b,a");
4429     lbl = newiTempLabel(NULL);
4430     pic16_emitcode("pop","acc");   
4431     /* if there was an over flow we don't 
4432     adjust the sign of the result */
4433     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4434     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4435     CLRC;
4436     pic16_emitcode("clr","a");
4437     pic16_emitcode("subb","a,b");
4438     pic16_emitcode("mov","b,a");
4439     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4440
4441     /* now we are done */
4442     pic16_aopPut(AOP(result),"b",0);
4443     if(size > 0){
4444         pic16_emitcode("mov","c,b.7");
4445         pic16_emitcode("subb","a,acc");   
4446     }
4447     while (size--)
4448         pic16_aopPut(AOP(result),"a",offset++);
4449
4450 }
4451
4452 /*-----------------------------------------------------------------*/
4453 /* genDiv - generates code for division                            */
4454 /*-----------------------------------------------------------------*/
4455 static void genDiv (iCode *ic)
4456 {
4457     operand *left = IC_LEFT(ic);
4458     operand *right = IC_RIGHT(ic);
4459     operand *result= IC_RESULT(ic);   
4460
4461
4462         /* Division is a very lengthy algorithm, so it is better
4463          * to call support routines than inlining algorithm.
4464          * Division functions written here just in case someone
4465          * wants to inline and not use the support libraries -- VR */
4466
4467     FENTRY;
4468     
4469     /* assign the amsops */
4470     pic16_aopOp (left,ic,FALSE);
4471     pic16_aopOp (right,ic,FALSE);
4472     pic16_aopOp (result,ic,TRUE);
4473
4474     /* special cases first */
4475     /* both are bits */
4476     if (AOP_TYPE(left) == AOP_CRY &&
4477         AOP_TYPE(right)== AOP_CRY) {
4478         genDivbits(left,right,result);
4479         goto release ;
4480     }
4481
4482     /* if both are of size == 1 */
4483     if (AOP_SIZE(left) == 1 &&
4484         AOP_SIZE(right) == 1 ) {
4485         genDivOneByte(left,right,result);
4486         goto release ;
4487     }
4488
4489     /* should have been converted to function call */
4490     assert(0);
4491 release :
4492     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4494     pic16_freeAsmop(result,NULL,ic,TRUE); 
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genModbits :- modulus of bits                                   */
4499 /*-----------------------------------------------------------------*/
4500 static void genModbits (operand *left, 
4501                         operand *right, 
4502                         operand *result)
4503 {
4504   char *l;
4505
4506     FENTRY;  
4507     
4508     werror(W_POSSBUG2, __FILE__, __LINE__);
4509     /* the result must be bit */    
4510     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4511     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4512
4513     MOVA(l);       
4514
4515     pic16_emitcode("div","ab");
4516     pic16_emitcode("mov","a,b");
4517     pic16_emitcode("rrc","a");
4518     pic16_aopPut(AOP(result),"c",0);
4519 }
4520
4521 /*-----------------------------------------------------------------*/
4522 /* genModOneByte : 8 bit modulus                                   */
4523 /*-----------------------------------------------------------------*/
4524 static void genModOneByte (operand *left,
4525                            operand *right,
4526                            operand *result)
4527 {
4528   sym_link *opetype = operandType(result);
4529   char *l ;
4530   symbol *lbl ;
4531
4532     FENTRY;
4533     werror(W_POSSBUG2, __FILE__, __LINE__);
4534
4535     /* signed or unsigned */
4536     if (SPEC_USIGN(opetype)) {
4537         /* unsigned is easy */
4538         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4539         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4540         MOVA(l);    
4541         pic16_emitcode("div","ab");
4542         pic16_aopPut(AOP(result),"b",0);
4543         return ;
4544     }
4545
4546     /* signed is a little bit more difficult */
4547
4548     /* save the signs of the operands */
4549     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4550     MOVA(l);
4551
4552     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4553     pic16_emitcode("push","acc"); /* save it on the stack */
4554
4555     /* now sign adjust for both left & right */
4556     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4557     MOVA(l);
4558
4559     lbl = newiTempLabel(NULL);
4560     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4561     pic16_emitcode("cpl","a");   
4562     pic16_emitcode("inc","a");
4563     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4564     pic16_emitcode("mov","b,a"); 
4565
4566     /* sign adjust left side */
4567     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4568     MOVA(l);
4569
4570     lbl = newiTempLabel(NULL);
4571     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4572     pic16_emitcode("cpl","a");   
4573     pic16_emitcode("inc","a");
4574     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4575
4576     /* now the multiplication */
4577     pic16_emitcode("div","ab");
4578     /* we are interested in the lower order
4579     only */
4580     lbl = newiTempLabel(NULL);
4581     pic16_emitcode("pop","acc");   
4582     /* if there was an over flow we don't 
4583     adjust the sign of the result */
4584     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4585     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4586     CLRC ;
4587     pic16_emitcode("clr","a");
4588     pic16_emitcode("subb","a,b");
4589     pic16_emitcode("mov","b,a");
4590     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4591
4592     /* now we are done */
4593     pic16_aopPut(AOP(result),"b",0);
4594
4595 }
4596
4597 /*-----------------------------------------------------------------*/
4598 /* genMod - generates code for division                            */
4599 /*-----------------------------------------------------------------*/
4600 static void genMod (iCode *ic)
4601 {
4602   operand *left = IC_LEFT(ic);
4603   operand *right = IC_RIGHT(ic);
4604   operand *result= IC_RESULT(ic);  
4605
4606     FENTRY;
4607     
4608     /* assign the amsops */
4609     pic16_aopOp (left,ic,FALSE);
4610     pic16_aopOp (right,ic,FALSE);
4611     pic16_aopOp (result,ic,TRUE);
4612
4613     /* special cases first */
4614     /* both are bits */
4615     if (AOP_TYPE(left) == AOP_CRY &&
4616         AOP_TYPE(right)== AOP_CRY) {
4617         genModbits(left,right,result);
4618         goto release ;
4619     }
4620
4621     /* if both are of size == 1 */
4622     if (AOP_SIZE(left) == 1 &&
4623         AOP_SIZE(right) == 1 ) {
4624         genModOneByte(left,right,result);
4625         goto release ;
4626     }
4627
4628     /* should have been converted to function call */
4629     assert(0);
4630
4631 release :
4632     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4633     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4634     pic16_freeAsmop(result,NULL,ic,TRUE); 
4635 }
4636
4637 /*-----------------------------------------------------------------*/
4638 /* genIfxJump :- will create a jump depending on the ifx           */
4639 /*-----------------------------------------------------------------*/
4640 /*
4641   note: May need to add parameter to indicate when a variable is in bit space.
4642 */
4643 static void genIfxJump (iCode *ic, char *jval)
4644 {
4645   FENTRY;
4646   
4647     /* if true label then we jump if condition
4648     supplied is true */
4649     if ( IC_TRUE(ic) ) {
4650
4651         if(strcmp(jval,"a") == 0)
4652           emitSKPZ;
4653         else if (strcmp(jval,"c") == 0)
4654           emitSKPNC;
4655         else {
4656           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4657           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4658         }
4659
4660         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4661         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4662
4663     }
4664     else {
4665         /* false label is present */
4666         if(strcmp(jval,"a") == 0)
4667           emitSKPNZ;
4668         else if (strcmp(jval,"c") == 0)
4669           emitSKPC;
4670         else {
4671           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4672           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4673         }
4674
4675         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4676         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4677
4678     }
4679
4680
4681     /* mark the icode as generated */
4682     ic->generated = 1;
4683 }
4684
4685 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4686 {
4687   FENTRY;
4688   
4689     /* if true label then we jump if condition
4690     supplied is true */
4691     if ( IC_TRUE(ic) ) {
4692       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4693       pic16_emitpcode(POC_BTFSC, jop);
4694
4695       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4696       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4697
4698     } else {
4699       /* false label is present */
4700       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4701       pic16_emitpcode(POC_BTFSS, jop);
4702           
4703       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4704       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4705     }
4706
4707
4708     /* mark the icode as generated */
4709     ic->generated = 1;
4710 }
4711
4712 #if 0
4713 // not needed ATM
4714
4715 /*-----------------------------------------------------------------*/
4716 /* genSkip                                                         */
4717 /*-----------------------------------------------------------------*/
4718 static void genSkip(iCode *ifx,int status_bit)
4719 {
4720   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4721   if(!ifx)
4722     return;
4723
4724   if ( IC_TRUE(ifx) ) {
4725     switch(status_bit) {
4726     case 'z':
4727       emitSKPNZ;
4728       break;
4729
4730     case 'c':
4731       emitSKPNC;
4732       break;
4733
4734     case 'd':
4735       emitSKPDC;
4736       break;
4737
4738     }
4739
4740     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4741     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4742
4743   } else {
4744
4745     switch(status_bit) {
4746
4747     case 'z':
4748       emitSKPZ;
4749       break;
4750
4751     case 'c':
4752       emitSKPC;
4753       break;
4754
4755     case 'd':
4756       emitSKPDC;
4757       break;
4758     }
4759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4760     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4761
4762   }
4763
4764 }
4765 #endif
4766
4767 /*-----------------------------------------------------------------*/
4768 /* genSkipc                                                        */
4769 /*-----------------------------------------------------------------*/
4770 static void genSkipc(resolvedIfx *rifx)
4771 {
4772   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4773   
4774   if(!rifx)
4775     return;
4776
4777   if(rifx->condition)
4778     emitSKPNC;
4779   else
4780     emitSKPC;
4781
4782   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4783   rifx->generated = 1;
4784 }
4785
4786 #if !(USE_SIMPLE_GENCMP)
4787 /*-----------------------------------------------------------------*/
4788 /* genSkipz2                                                       */
4789 /*-----------------------------------------------------------------*/
4790 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4791 {
4792   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4793   
4794   if(!rifx)
4795     return;
4796
4797   if( (rifx->condition ^ invert_condition) & 1)
4798     emitSKPZ;
4799   else
4800     emitSKPNZ;
4801
4802   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4803   rifx->generated = 1;
4804 }
4805 #endif
4806
4807 #if 0
4808 /*-----------------------------------------------------------------*/
4809 /* genSkipz                                                        */
4810 /*-----------------------------------------------------------------*/
4811 static void genSkipz(iCode *ifx, int condition)
4812 {
4813   if(!ifx)
4814     return;
4815
4816   if(condition)
4817     emitSKPNZ;
4818   else
4819     emitSKPZ;
4820
4821   if ( IC_TRUE(ifx) )
4822     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4823   else
4824     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4825
4826   if ( IC_TRUE(ifx) )
4827     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4828   else
4829     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4830
4831 }
4832 #endif
4833
4834 #if !(USE_SIMPLE_GENCMP)
4835 /*-----------------------------------------------------------------*/
4836 /* genSkipCond                                                     */
4837 /*-----------------------------------------------------------------*/
4838 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4839 {
4840   if(!rifx)
4841     return;
4842
4843   if(rifx->condition)
4844     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4845   else
4846     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4847
4848
4849   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4850   rifx->generated = 1;
4851 }
4852 #endif
4853
4854 #if 0
4855 /*-----------------------------------------------------------------*/
4856 /* genChkZeroes :- greater or less than comparison                 */
4857 /*     For each byte in a literal that is zero, inclusive or the   */
4858 /*     the corresponding byte in the operand with W                */
4859 /*     returns true if any of the bytes are zero                   */
4860 /*-----------------------------------------------------------------*/
4861 static int genChkZeroes(operand *op, int lit,  int size)
4862 {
4863
4864   int i;
4865   int flag =1;
4866
4867   while(size--) {
4868     i = (lit >> (size*8)) & 0xff;
4869
4870     if(i==0) {
4871       if(flag) 
4872         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4873       else
4874         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4875       flag = 0;
4876     }
4877   }
4878
4879   return (flag==0);
4880 }
4881 #endif
4882
4883
4884 /*-----------------------------------------------------------------*/
4885 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4886 /*                  aop (if it's NOT a literal) or from lit (if    */
4887 /*                  aop is a literal)                              */
4888 /*-----------------------------------------------------------------*/
4889 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4890   if (aop->type == AOP_LIT) {
4891     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4892   } else {
4893     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4894   }
4895 }
4896
4897 /*-----------------------------------------------------------------*/
4898 /* genCmp :- greater or less than comparison                       */
4899 /*-----------------------------------------------------------------*/
4900
4901 #if USE_SIMPLE_GENCMP           /* { */
4902
4903 /* genCmp performs a left < right comparison, stores
4904  * the outcome in result (if != NULL) and generates
4905  * control flow code for the ifx (if != NULL).
4906  *
4907  * This version leaves in sequences like
4908  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4909  * which should be optmized by the peephole
4910  * optimizer - RN 2005-01-01 */
4911 static void genCmp (operand *left,operand *right,
4912                     operand *result, iCode *ifx, int sign)
4913 {
4914   resolvedIfx rIfx;
4915   int size;
4916   int offs;
4917   symbol *templbl;
4918   operand *dummy;
4919   unsigned long lit;
4920   unsigned long mask;
4921   int performedLt;
4922
4923   FENTRY;
4924   
4925   assert (left && right);
4926   assert (AOP_SIZE(left) == AOP_SIZE(right));
4927
4928   size = AOP_SIZE(right) - 1;
4929   mask = (0x100UL << (size*8)) - 1;
4930   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4931   performedLt = 1;
4932   templbl = NULL;
4933   lit = 0;
4934   
4935   resolveIfx (&rIfx, ifx);
4936
4937   /* handle for special cases */
4938   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4939       return;
4940
4941   /**********************************************************************
4942    * handle bits - bit compares are promoted to int compares seemingly! *
4943    **********************************************************************/
4944 #if 0
4945   // THIS IS COMPLETELY UNTESTED!
4946   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4947     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4948     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4949     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4950
4951     emitSETC;
4952     // 1 < {0,1} is false --> clear C by skipping the next instruction
4953     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4954     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4955     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4956     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4957     emitCLRC; // only skipped for left=0 && right=1
4958
4959     goto correct_result_in_carry;
4960   } // if
4961 #endif
4962
4963   /*************************************************
4964    * make sure that left is register (or the like) *
4965    *************************************************/
4966   if (!isAOP_REGlike(left)) {
4967     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4968     assert (isAOP_LIT(left));
4969     assert (isAOP_REGlike(right));
4970     // swap left and right
4971     // left < right <==> right > left <==> (right >= left + 1)
4972     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4973
4974     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4975       // MAXVALUE < right? always false
4976       if (performedLt) emitCLRC; else emitSETC;
4977       goto correct_result_in_carry;
4978     } // if
4979
4980     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4981     // that's why we handled it above.
4982     lit++;
4983
4984     dummy = left;
4985     left = right;
4986     right = dummy;
4987
4988     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4989   } else if (isAOP_LIT(right)) {
4990     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4991   } // if
4992
4993   assert (isAOP_REGlike(left)); // left must be register or the like
4994   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4995
4996   /*************************************************
4997    * special cases go here                         *
4998    *************************************************/
4999
5000   if (isAOP_LIT(right)) {
5001     if (!sign) {
5002       // unsigned comparison to a literal
5003       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5004       if (lit == 0) {
5005         // unsigned left < 0? always false
5006         if (performedLt) emitCLRC; else emitSETC;
5007         goto correct_result_in_carry;
5008       }
5009     } else {
5010       // signed comparison to a literal
5011       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5012       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5013         // signed left < 0x80000000? always false
5014         if (performedLt) emitCLRC; else emitSETC;
5015         goto correct_result_in_carry;
5016       } else if (lit == 0) {
5017         // compare left < 0; set CARRY if SIGNBIT(left) is set
5018         if (performedLt) emitSETC; else emitCLRC;
5019         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5020         if (performedLt) emitCLRC; else emitSETC;
5021         goto correct_result_in_carry;
5022       }
5023     } // if (!sign)
5024   } // right is literal
5025
5026   /*************************************************
5027    * perform a general case comparison             *
5028    * make sure we get CARRY==1 <==> left >= right  *
5029    *************************************************/
5030   // compare most significant bytes
5031   //DEBUGpc ("comparing bytes at offset %d", size);
5032   if (!sign) {
5033     // unsigned comparison
5034     mov2w_regOrLit (AOP(right), lit, size);
5035     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5036   } else {
5037     // signed comparison
5038     // (add 2^n to both operands then perform an unsigned comparison)
5039     if (isAOP_LIT(right)) {
5040       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5041       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5042
5043       if (litbyte == 0x80) {
5044         // left >= 0x80 -- always true, but more bytes to come
5045         pic16_mov2w (AOP(left), size);
5046         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5047         emitSETC;
5048       } else {
5049         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5050         pic16_mov2w (AOP(left), size);
5051         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5052         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5053       } // if
5054     } else {
5055       /* using PRODL as a temporary register here */
5056       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5057       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5058       pic16_mov2w (AOP(left), size);
5059       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5060       pic16_emitpcode (POC_MOVWF, pctemp);
5061       pic16_mov2w (AOP(right), size);
5062       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5063       pic16_emitpcode (POC_SUBFW, pctemp);
5064       //pic16_popReleaseTempReg(pctemp, 1);
5065     }
5066   } // if (!sign)
5067
5068   // compare remaining bytes (treat as unsigned case from above)
5069   templbl = newiTempLabel ( NULL );
5070   offs = size;
5071   while (offs--) {
5072     //DEBUGpc ("comparing bytes at offset %d", offs);
5073     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5074     mov2w_regOrLit (AOP(right), lit, offs);
5075     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5076   } // while (offs)
5077   pic16_emitpLabel (templbl->key);
5078   goto result_in_carry;
5079
5080 result_in_carry:
5081   
5082   /****************************************************
5083    * now CARRY contains the result of the comparison: *
5084    * SUBWF sets CARRY iff                             *
5085    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5086    * (F=left, W=right)                                *
5087    ****************************************************/
5088
5089   if (performedLt) {
5090     if (result && AOP_TYPE(result) != AOP_CRY) {
5091       // value will be stored
5092       emitTOGC;
5093     } else {
5094       // value wil only be used in the following genSkipc()
5095       rIfx.condition ^= 1;
5096     }
5097   } // if
5098
5099 correct_result_in_carry:
5100
5101   // assign result to variable (if neccessary)
5102   if (result && AOP_TYPE(result) != AOP_CRY) {
5103     //DEBUGpc ("assign result");
5104     size = AOP_SIZE(result);
5105     while (size--) {
5106       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5107     } // while
5108     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5109   } // if (result)
5110
5111   // perform conditional jump
5112   if (ifx) {
5113     //DEBUGpc ("generate control flow");
5114     genSkipc (&rIfx);
5115     ifx->generated = 1;
5116   } // if
5117 }
5118
5119 #elif 1         /* } */
5120                 /* { */
5121       /* original code */
5122 static void genCmp (operand *left,operand *right,
5123                     operand *result, iCode *ifx, int sign)
5124 {
5125   int size; //, offset = 0 ;
5126   unsigned long lit = 0L,i = 0;
5127   resolvedIfx rFalseIfx;
5128   //  resolvedIfx rTrueIfx;
5129   symbol *truelbl;
5130   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5131 /*
5132   if(ifx) {
5133     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5134     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5135   }
5136 */
5137
5138   FENTRY;
5139   
5140   resolveIfx(&rFalseIfx,ifx);
5141   truelbl  = newiTempLabel(NULL);
5142   size = max(AOP_SIZE(left),AOP_SIZE(right));
5143
5144   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5145
5146 #define _swapp
5147
5148   /* if literal is on the right then swap with left */
5149   if ((AOP_TYPE(right) == AOP_LIT)) {
5150     operand *tmp = right ;
5151     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5152     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5153 #ifdef _swapp
5154
5155     lit = (lit - 1) & mask;
5156     right = left;
5157     left = tmp;
5158     rFalseIfx.condition ^= 1;
5159 #endif
5160
5161   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5162     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5163   }
5164
5165
5166   //if(IC_TRUE(ifx) == NULL)
5167   /* if left & right are bit variables */
5168   if (AOP_TYPE(left) == AOP_CRY &&
5169       AOP_TYPE(right) == AOP_CRY ) {
5170     assert (0 && "bit variables used in genCmp");
5171     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5172     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5173   } else {
5174     /* subtract right from left if at the
5175        end the carry flag is set then we know that
5176        left is greater than right */
5177
5178     symbol *lbl  = newiTempLabel(NULL);
5179
5180 #if 0
5181         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5182                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5183 #endif
5184
5185 #ifndef _swapp
5186     if(AOP_TYPE(right) == AOP_LIT) {
5187
5188       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5189
5190       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5191
5192       /* special cases */
5193
5194       if(lit == 0) {
5195
5196         if(sign != 0) 
5197           genSkipCond(&rFalseIfx,left,size-1,7);
5198         else 
5199           /* no need to compare to 0...*/
5200           /* NOTE: this is a de-generate compare that most certainly 
5201            *       creates some dead code. */
5202           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5203
5204         if(ifx) ifx->generated = 1;
5205         return;
5206
5207       }
5208       size--;
5209
5210       if(size == 0) {
5211         //i = (lit >> (size*8)) & 0xff;
5212         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5213         
5214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5215
5216         i = ((0-lit) & 0xff);
5217         if(sign) {
5218           if( i == 0x81) { 
5219             /* lit is 0x7f, all signed chars are less than
5220              * this except for 0x7f itself */
5221             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5222             genSkipz2(&rFalseIfx,0);
5223           } else {
5224             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5225             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5226             genSkipc(&rFalseIfx);
5227           }
5228
5229         } else {
5230           if(lit == 1) {
5231             genSkipz2(&rFalseIfx,1);
5232           } else {
5233             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5234             genSkipc(&rFalseIfx);
5235           }
5236         }
5237
5238         if(ifx) ifx->generated = 1;
5239         return;
5240       }
5241
5242       /* chars are out of the way. now do ints and longs */
5243
5244
5245       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5246         
5247       /* special cases */
5248
5249       if(sign) {
5250
5251         if(lit == 0) {
5252           genSkipCond(&rFalseIfx,left,size,7);
5253           if(ifx) ifx->generated = 1;
5254           return;
5255         }
5256
5257         if(lit <0x100) {
5258           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5259
5260           //rFalseIfx.condition ^= 1;
5261           //genSkipCond(&rFalseIfx,left,size,7);
5262           //rFalseIfx.condition ^= 1;
5263
5264           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5265           if(rFalseIfx.condition)
5266             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5267           else
5268             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5269
5270           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5271           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5272           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5273
5274           while(size > 1)
5275             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5276
5277           if(rFalseIfx.condition) {
5278             emitSKPZ;
5279             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5280
5281           } else {
5282             emitSKPNZ;
5283           }
5284
5285           genSkipc(&rFalseIfx);
5286           pic16_emitpLabel(truelbl->key);
5287           if(ifx) ifx->generated = 1;
5288           return;
5289
5290         }
5291
5292         if(size == 1) {
5293
5294           if( (lit & 0xff) == 0) {
5295             /* lower byte is zero */
5296             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5297             i = ((lit >> 8) & 0xff) ^0x80;
5298             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5301             genSkipc(&rFalseIfx);
5302
5303
5304             if(ifx) ifx->generated = 1;
5305             return;
5306
5307           }
5308         } else {
5309           /* Special cases for signed longs */
5310           if( (lit & 0xffffff) == 0) {
5311             /* lower byte is zero */
5312             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5313             i = ((lit >> 8*3) & 0xff) ^0x80;
5314             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5315             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5316             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5317             genSkipc(&rFalseIfx);
5318
5319
5320             if(ifx) ifx->generated = 1;
5321             return;
5322
5323           }
5324
5325         }
5326
5327
5328         if(lit & (0x80 << (size*8))) {
5329           /* lit is negative */
5330           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5331
5332           //genSkipCond(&rFalseIfx,left,size,7);
5333
5334           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5335
5336           if(rFalseIfx.condition)
5337             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5338           else
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5340
5341
5342         } else {
5343           /* lit is positive */
5344           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5345           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5346           if(rFalseIfx.condition)
5347             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5348           else
5349             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5350
5351         }
5352
5353         /*
5354           This works, but is only good for ints.
5355           It also requires a "known zero" register.
5356           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5357           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5358           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5359           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5360           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5361           genSkipc(&rFalseIfx);
5362
5363           pic16_emitpLabel(truelbl->key);
5364           if(ifx) ifx->generated = 1;
5365           return;
5366         **/
5367           
5368         /* There are no more special cases, so perform a general compare */
5369   
5370         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5371         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5372
5373         while(size--) {
5374
5375           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5376           emitSKPNZ;
5377           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5378         }
5379         //rFalseIfx.condition ^= 1;
5380         genSkipc(&rFalseIfx);
5381
5382         pic16_emitpLabel(truelbl->key);
5383
5384         if(ifx) ifx->generated = 1;
5385         return;
5386
5387
5388       }
5389
5390
5391       /* sign is out of the way. So now do an unsigned compare */
5392       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5393
5394
5395       /* General case - compare to an unsigned literal on the right.*/
5396
5397       i = (lit >> (size*8)) & 0xff;
5398       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5399       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5400       while(size--) {
5401         i = (lit >> (size*8)) & 0xff;
5402
5403         if(i) {
5404           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5405           emitSKPNZ;
5406           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5407         } else {
5408           /* this byte of the lit is zero, 
5409            *if it's not the last then OR in the variable */
5410           if(size)
5411             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5412         }
5413       }
5414
5415
5416       pic16_emitpLabel(lbl->key);
5417 //      pic16_emitpLabel(truelbl->key);
5418       //if(emitFinalCheck)
5419       genSkipc(&rFalseIfx);
5420       if(sign)
5421         pic16_emitpLabel(truelbl->key);
5422
5423       if(ifx) ifx->generated = 1;
5424       return;
5425
5426
5427     }
5428 #endif  // _swapp
5429
5430     if(AOP_TYPE(left) == AOP_LIT) {
5431       //symbol *lbl = newiTempLabel(NULL);
5432
5433       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5434
5435
5436       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5437
5438       /* Special cases */
5439       if((lit == 0) && (sign == 0)){
5440
5441         size--;
5442         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5443         while(size) 
5444           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5445
5446         genSkipz2(&rFalseIfx,0);
5447         if(ifx) ifx->generated = 1;
5448         return;
5449       }
5450
5451       if(size==1) {
5452         /* Special cases */
5453         lit &= 0xff;
5454         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5455           /* degenerate compare can never be true */
5456           if(rFalseIfx.condition == 0)
5457             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5458
5459           if(ifx) ifx->generated = 1;
5460           return;
5461         }
5462
5463         if(sign) {
5464           /* signed comparisons to a literal byte */
5465
5466           int lp1 = (lit+1) & 0xff;
5467
5468           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5469           switch (lp1) {
5470           case 0:
5471             rFalseIfx.condition ^= 1;
5472             genSkipCond(&rFalseIfx,right,0,7);
5473             break;
5474           case 0x7f:
5475             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5476             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5477             genSkipz2(&rFalseIfx,1);
5478             break;
5479           default:
5480             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5481             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5482             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5483             rFalseIfx.condition ^= 1;
5484             genSkipc(&rFalseIfx);
5485             break;
5486           }
5487         } else {
5488           /* unsigned comparisons to a literal byte */
5489
5490           switch(lit & 0xff ) {
5491           case 0:
5492             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5493             genSkipz2(&rFalseIfx,0);
5494             break;
5495           case 0x7f:
5496             rFalseIfx.condition ^= 1;
5497             genSkipCond(&rFalseIfx,right,0,7);
5498             break;
5499
5500           default:
5501             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5502             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5503             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5504             rFalseIfx.condition ^= 1;
5505             if (AOP_TYPE(result) == AOP_CRY)
5506               genSkipc(&rFalseIfx);
5507             else {
5508               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5509               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5510             }         
5511             break;
5512           }
5513         }
5514
5515         if(ifx) ifx->generated = 1;
5516         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5517                 goto check_carry;
5518         return;
5519
5520       } else {
5521
5522         /* Size is greater than 1 */
5523
5524         if(sign) {
5525           int lp1 = lit+1;
5526
5527           size--;
5528
5529           if(lp1 == 0) {
5530             /* this means lit = 0xffffffff, or -1 */
5531
5532
5533             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5534             rFalseIfx.condition ^= 1;
5535             genSkipCond(&rFalseIfx,right,size,7);
5536             if(ifx) ifx->generated = 1;
5537
5538             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5539               goto check_carry;
5540
5541             return;
5542           }
5543
5544           if(lit == 0) {
5545             int s = size;
5546
5547             if(rFalseIfx.condition) {
5548               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5549               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5550             }
5551
5552             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5553             while(size--)
5554               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5555
5556
5557             emitSKPZ;
5558             if(rFalseIfx.condition) {
5559               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5560               pic16_emitpLabel(truelbl->key);
5561             }else {
5562               rFalseIfx.condition ^= 1;
5563               genSkipCond(&rFalseIfx,right,s,7);
5564             }
5565
5566             if(ifx) ifx->generated = 1;
5567
5568             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5569               goto check_carry;
5570
5571             return;
5572           }
5573
5574           if((size == 1) &&  (0 == (lp1&0xff))) {
5575             /* lower byte of signed word is zero */
5576             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5577             i = ((lp1 >> 8) & 0xff) ^0x80;
5578             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5579             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5580             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5581
5582             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5583               emitTOGC;
5584               if(ifx) ifx->generated = 1;
5585               goto check_carry;
5586             } else {
5587               rFalseIfx.condition ^= 1;
5588               genSkipc(&rFalseIfx);
5589               if(ifx) ifx->generated = 1;
5590             }
5591
5592             return;
5593           }
5594
5595           if(lit & (0x80 << (size*8))) {
5596             /* Lit is less than zero */
5597             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5598             //rFalseIfx.condition ^= 1;
5599             //genSkipCond(&rFalseIfx,left,size,7);
5600             //rFalseIfx.condition ^= 1;
5601             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5602             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5603
5604             if(rFalseIfx.condition)
5605               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5606             else
5607               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5608
5609
5610           } else {
5611             /* Lit is greater than or equal to zero */
5612             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5613             //rFalseIfx.condition ^= 1;
5614             //genSkipCond(&rFalseIfx,right,size,7);
5615             //rFalseIfx.condition ^= 1;
5616
5617             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5618             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5619
5620             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5621             if(rFalseIfx.condition)
5622               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5623             else
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5625
5626           }
5627
5628           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5629           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5630
5631           while(size--) {
5632
5633             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5634             emitSKPNZ;
5635             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5636           }
5637           rFalseIfx.condition ^= 1;
5638           //rFalseIfx.condition = 1;
5639           genSkipc(&rFalseIfx);
5640
5641           pic16_emitpLabel(truelbl->key);
5642
5643           if(ifx) ifx->generated = 1;
5644
5645
5646           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5647             goto check_carry;
5648
5649           return;
5650           // end of if (sign)
5651         } else {
5652
5653           /* compare word or long to an unsigned literal on the right.*/
5654
5655
5656           size--;
5657           if(lit < 0xff) {
5658             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5659             switch (lit) {
5660             case 0:
5661               break; /* handled above */
5662 /*
5663             case 0xff:
5664               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5665               while(size--)
5666                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5667               genSkipz2(&rFalseIfx,0);
5668               break;
5669 */
5670             default:
5671               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5672               while(--size)
5673                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5674
5675               emitSKPZ;
5676               if(rFalseIfx.condition)
5677                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5678               else
5679                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5680
5681
5682               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5683               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5684
5685               rFalseIfx.condition ^= 1;
5686               genSkipc(&rFalseIfx);
5687             }
5688
5689             pic16_emitpLabel(truelbl->key);
5690
5691             if(ifx) ifx->generated = 1;
5692
5693             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5694               goto check_carry;
5695
5696             return;
5697           }
5698
5699
5700           lit++;
5701           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5702           i = (lit >> (size*8)) & 0xff;
5703
5704           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5705           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5706
5707           while(size--) {
5708             i = (lit >> (size*8)) & 0xff;
5709
5710             if(i) {
5711               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5712               emitSKPNZ;
5713               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5714             } else {
5715               /* this byte of the lit is zero, 
5716                * if it's not the last then OR in the variable */
5717               if(size)
5718                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5719             }
5720           }
5721
5722
5723           pic16_emitpLabel(lbl->key);
5724
5725           rFalseIfx.condition ^= 1;
5726
5727           genSkipc(&rFalseIfx);
5728         }
5729
5730         if(sign)
5731           pic16_emitpLabel(truelbl->key);
5732         if(ifx) ifx->generated = 1;
5733
5734             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5735               goto check_carry;
5736
5737         return;
5738       }
5739     }
5740     /* Compare two variables */
5741
5742     DEBUGpic16_emitcode(";sign","%d",sign);
5743
5744     size--;
5745     if(sign) {
5746       /* Sigh. thus sucks... */
5747       if(size) {
5748         pCodeOp *pctemp;
5749         
5750         pctemp = pic16_popGetTempReg(1);
5751         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5752         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5753         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5754         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5755         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5756         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5757         pic16_popReleaseTempReg(pctemp, 1);
5758       } else {
5759         /* Signed char comparison */
5760         /* Special thanks to Nikolai Golovchenko for this snippet */
5761         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5762         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5763         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5764         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5765         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5766         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5767
5768         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5769         genSkipc(&rFalseIfx);
5770           
5771         if(ifx) ifx->generated = 1;
5772
5773             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5774               goto check_carry;
5775
5776         return;
5777       }
5778
5779     } else {
5780
5781       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5782       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5783     }
5784
5785
5786     /* The rest of the bytes of a multi-byte compare */
5787     while (size) {
5788
5789       emitSKPZ;
5790       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5791       size--;
5792
5793       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5794       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5795
5796
5797     }
5798
5799     pic16_emitpLabel(lbl->key);
5800
5801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5802     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5803         (AOP_TYPE(result) == AOP_REG)) {
5804       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5805       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5806     } else {
5807       genSkipc(&rFalseIfx);
5808     }         
5809     //genSkipc(&rFalseIfx);
5810     if(ifx) ifx->generated = 1;
5811
5812
5813             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5814               goto check_carry;
5815
5816     return;
5817
5818   }
5819
5820 check_carry:
5821   if ((AOP_TYPE(result) != AOP_CRY) 
5822         && AOP_SIZE(result)) {
5823     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824
5825     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5826
5827     pic16_outBitC(result);
5828   } else {
5829     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5830     /* if the result is used in the next
5831        ifx conditional branch then generate
5832        code a little differently */
5833     if (ifx )
5834       genIfxJump (ifx,"c");
5835     else
5836       pic16_outBitC(result);
5837     /* leave the result in acc */
5838   }
5839
5840 }
5841
5842 #elif 0 /* VR version of genCmp() */    /* } else { */
5843
5844 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5845 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5846         operand *result, int offset, int invert_op)
5847 {
5848   /* add code here */
5849   
5850   /* check condition, > or < ?? */
5851   if(rIfx->condition != 0)invert_op ^= 1;
5852   
5853   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5854
5855   if(!ifx)invert_op ^= 1;
5856
5857   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5858       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5859   
5860   /* do selection */
5861   if(!invert_op)return POC_CPFSGT;
5862   else return POC_CPFSLT;
5863 }
5864
5865 static int compareAopfirstpass=1;
5866
5867 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5868             operand *oper, int offset, operand *result,
5869             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5870             symbol *tlbl)
5871 {
5872   int op;
5873   symbol *truelbl;
5874
5875   /* invert if there is a result to be loaded, in order to fit,
5876    * SETC/CLRC sequence */
5877   if(AOP_SIZE(result))invert_op ^= 1;
5878
5879 //  if(sign && !offset)invert_op ^= 1;
5880   
5881 //  if(sign)invert_op ^= 1;
5882   
5883   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5884
5885   if(AOP_SIZE(result) && compareAopfirstpass) {
5886     if(!ifx) {
5887       if(pcop2)
5888         pic16_emitpcode(POC_SETF, pcop2);
5889       else
5890         emitSETC;
5891     } else {
5892       if(pcop2)
5893         pic16_emitpcode(POC_CLRF, pcop2);
5894       else
5895         emitCLRC;
5896     }
5897   }
5898
5899   compareAopfirstpass = 0;
5900
5901       /* there is a bug when comparing operands with size > 1,
5902        * because higher bytes can be equal and test should be performed
5903        * to the next lower byte, current algorithm, considers operands
5904        * inequal in these cases! -- VR 20041107 */
5905
5906     
5907   if(pcop)
5908     pic16_emitpcode(op, pcop);
5909   else
5910     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5911
5912
5913   if((!sign || !offset) && AOP_SIZE(result)) {
5914     if(!ifx) {
5915       if(pcop2)
5916         pic16_emitpcode(POC_CLRF, pcop2);
5917         else
5918         emitCLRC;
5919     } else {
5920       if(pcop2)
5921         pic16_emitpcode(POC_SETF, pcop2);
5922       else
5923         emitSETC;
5924     }
5925     
5926     /* don't emit final branch (offset == 0) */
5927     if(offset) {
5928
5929       if(pcop2)
5930         pic16_emitpcode(POC_RRCF, pcop2);
5931
5932       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5933     }
5934   } else {
5935     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5936       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5937             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5938
5939       truelbl = newiTempLabel( NULL );
5940       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5941       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5942         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5943       else
5944         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5945       pic16_emitpLabel(truelbl->key);
5946     } else {
5947       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5948     }
5949   }
5950 }
5951
5952 static void genCmp (operand *left, operand *right,
5953                     operand *result, iCode *ifx, int sign)
5954 {
5955   int size, cmpop=1;
5956   long lit = 0L;
5957   resolvedIfx rFalseIfx;
5958   symbol *falselbl, *tlbl;
5959
5960     FENTRY;
5961     
5962     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5963
5964     resolveIfx(&rFalseIfx, ifx);
5965     size = max(AOP_SIZE(left), AOP_SIZE(right));
5966     
5967     /* if left & right are bit variables */
5968     if(AOP_TYPE(left) == AOP_CRY
5969       && AOP_TYPE(right) == AOP_CRY ) {
5970
5971         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5972         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5973         
5974         werror(W_POSSBUG2, __FILE__, __LINE__);
5975         exit(-1);
5976     }
5977     
5978     /* if literal is on the right then swap with left */
5979     if((AOP_TYPE(right) == AOP_LIT)) {
5980       operand *tmp = right ;
5981 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5982
5983         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5984
5985 //      lit = (lit - 1) & mask;
5986         right = left;
5987         left = tmp;
5988         rFalseIfx.condition ^= 1;               /* reverse compare */
5989     } else
5990     if ((AOP_TYPE(left) == AOP_LIT)) {
5991       /* float compares are handled by support functions */
5992       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5993     }
5994
5995     /* actual comparing algorithm */
5996 //    size = AOP_SIZE( right );
5997
5998     falselbl = newiTempLabel( NULL );
5999     if(AOP_TYPE(left) == AOP_LIT) {
6000       /* compare to literal */
6001       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6002       
6003       if(sign) {
6004         pCodeOp *pct, *pct2;
6005         symbol *tlbl1;
6006
6007         /* signed compare */
6008         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6009
6010         /* using PRODL:PRODH as a temporary register here */
6011         pct = pic16_popCopyReg(&pic16_pc_prodl);
6012         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6013         tlbl = newiTempLabel( NULL );
6014         
6015         /* first compare signs:
6016          *  a. if both are positive, compare just like unsigned
6017          *  b. if both are negative, invert cmpop, compare just like unsigned
6018          *  c. if different signs, determine the result directly */
6019
6020         size--;
6021
6022 #if 1
6023         /* { */
6024         tlbl1 = newiTempLabel( NULL );
6025 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6026
6027         if(lit > 0) {
6028
6029           /* literal is zero or positive:
6030            *  a. if carry is zero, too, continue compare,
6031            *  b. if carry is set, then continue depending on cmpop ^ condition:
6032            *    1. '<' return false (literal < variable),
6033            *    2. '>' return true (literal > variable) */
6034 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6035           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6036           
6037           
6038           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6039           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6040         } else 
6041         if(lit < 0) {
6042           
6043           /* literal is negative:
6044            *  a. if carry is set, too, continue compare,
6045            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6046            *    1. '<' return true (literal < variable),
6047            *    2. '>' return false (literal > variable) */
6048 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6049           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6050           
6051           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6052           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6053         }
6054 #if 1
6055         else {
6056           /* lit == 0 */
6057           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6058           
6059           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6060           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6061         }
6062 #endif
6063         
6064         
6065         pic16_emitpLabel( tlbl1->key );
6066 #endif  /* } */
6067
6068         compareAopfirstpass=1;
6069 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6070 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6071 //        pic16_emitpcode(POC_MOVWF, pct);
6072
6073 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6074         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6075 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6076         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6077
6078         /* generic case */        
6079           while( size-- ) {
6080 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6081 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6082 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6083 //            pic16_emitpcode(POC_MOVWF, pct);
6084
6085 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6086             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6087             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6088 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6089 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6090           }
6091         
6092         if(ifx)ifx->generated = 1;
6093
6094         if(AOP_SIZE(result)) {
6095           pic16_emitpLabel(tlbl->key);
6096           pic16_emitpLabel(falselbl->key);
6097           pic16_outBitOp( result, pct2 );
6098         } else {
6099           pic16_emitpLabel(tlbl->key);
6100         }
6101       } else {
6102
6103         /* unsigned compare */      
6104         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6105     
6106         compareAopfirstpass=1;
6107         while(size--) {
6108           
6109           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6110           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6111
6112         }
6113         if(ifx)ifx->generated = 1;
6114
6115         if(AOP_SIZE(result)) {
6116           pic16_emitpLabel(falselbl->key);
6117           pic16_outBitC( result );
6118         }
6119
6120       }
6121     } else {
6122       /* compare registers */
6123       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6124
6125
6126       if(sign) {
6127         pCodeOp *pct, *pct2;
6128         
6129         /* signed compare */
6130         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6131
6132         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6133         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6134         tlbl = newiTempLabel( NULL );
6135         
6136         compareAopfirstpass=1;
6137
6138         size--;
6139         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6140 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6141         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6142         pic16_emitpcode(POC_MOVWF, pct);
6143
6144         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6145 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6146         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6147
6148         /* WREG already holds left + 0x80 */
6149         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6150         
6151         while( size-- ) {
6152           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6153 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6154           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6155           pic16_emitpcode(POC_MOVWF, pct);
6156                 
6157           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6159           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6160
6161           /* WREG already holds left + 0x80 */
6162           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6163 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6164         }
6165         
6166         if(ifx)ifx->generated = 1;
6167
6168         if(AOP_SIZE(result)) {
6169           pic16_emitpLabel(tlbl->key);
6170           pic16_emitpLabel(falselbl->key);
6171           pic16_outBitOp( result, pct2 );
6172         } else {
6173           pic16_emitpLabel(tlbl->key);
6174         }
6175
6176       } else {
6177         /* unsigned compare */      
6178         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6179
6180         compareAopfirstpass=1;
6181         while(size--) {
6182           
6183           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6184           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6185
6186         }
6187
6188         if(ifx)ifx->generated = 1;
6189         if(AOP_SIZE(result)) {
6190
6191           pic16_emitpLabel(falselbl->key);
6192           pic16_outBitC( result );
6193         }
6194
6195       }
6196     }
6197 }
6198
6199 #endif  /* } */
6200
6201
6202
6203 /*-----------------------------------------------------------------*/
6204 /* genCmpGt :- greater than comparison                             */
6205 /*-----------------------------------------------------------------*/
6206 static void genCmpGt (iCode *ic, iCode *ifx)
6207 {
6208   operand *left, *right, *result;
6209   sym_link *letype , *retype;
6210   int sign ;
6211
6212     FENTRY;
6213     
6214     left = IC_LEFT(ic);
6215     right= IC_RIGHT(ic);
6216     result = IC_RESULT(ic);
6217
6218     letype = getSpec(operandType(left));
6219     retype =getSpec(operandType(right));
6220     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6221     /* assign the amsops */
6222     pic16_aopOp (left,ic,FALSE);
6223     pic16_aopOp (right,ic,FALSE);
6224     pic16_aopOp (result,ic,TRUE);
6225
6226     genCmp(right, left, result, ifx, sign);
6227
6228     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6229     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6230     pic16_freeAsmop(result,NULL,ic,TRUE); 
6231 }
6232
6233 /*-----------------------------------------------------------------*/
6234 /* genCmpLt - less than comparisons                                */
6235 /*-----------------------------------------------------------------*/
6236 static void genCmpLt (iCode *ic, iCode *ifx)
6237 {
6238   operand *left, *right, *result;
6239   sym_link *letype , *retype;
6240   int sign ;
6241
6242     FENTRY;
6243
6244     left = IC_LEFT(ic);
6245     right= IC_RIGHT(ic);
6246     result = IC_RESULT(ic);
6247
6248     letype = getSpec(operandType(left));
6249     retype =getSpec(operandType(right));
6250     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6251
6252     /* assign the amsops */
6253     pic16_aopOp (left,ic,FALSE);
6254     pic16_aopOp (right,ic,FALSE);
6255     pic16_aopOp (result,ic,TRUE);
6256
6257     genCmp(left, right, result, ifx, sign);
6258
6259     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6261     pic16_freeAsmop(result,NULL,ic,TRUE); 
6262 }
6263
6264 #if 0
6265 // not needed ATM
6266 // FIXME reenable literal optimisation when the pic16 port is stable
6267
6268 /*-----------------------------------------------------------------*/
6269 /* genc16bit2lit - compare a 16 bit value to a literal             */
6270 /*-----------------------------------------------------------------*/
6271 static void genc16bit2lit(operand *op, int lit, int offset)
6272 {
6273   int i;
6274
6275   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6276   if( (lit&0xff) == 0) 
6277     i=1;
6278   else
6279     i=0;
6280
6281   switch( BYTEofLONG(lit,i)) { 
6282   case 0:
6283     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6284     break;
6285   case 1:
6286     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6287     break;
6288   case 0xff:
6289     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6290     break;
6291   default:
6292     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6293     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6294   }
6295
6296   i ^= 1;
6297
6298   switch( BYTEofLONG(lit,i)) { 
6299   case 0:
6300     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6301     break;
6302   case 1:
6303     emitSKPNZ;
6304     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6305     break;
6306   case 0xff:
6307     emitSKPNZ;
6308     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6309     break;
6310   default:
6311     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6312     emitSKPNZ;
6313     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6314
6315   }
6316
6317 }
6318 #endif
6319
6320 #if 0
6321 // not needed ATM
6322 /*-----------------------------------------------------------------*/
6323 /* gencjneshort - compare and jump if not equal                    */
6324 /*-----------------------------------------------------------------*/
6325 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6326 {
6327   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6328   int offset = 0;
6329   int res_offset = 0;  /* the result may be a different size then left or right */
6330   int res_size = AOP_SIZE(result);
6331   resolvedIfx rIfx;
6332   symbol *lbl, *lbl_done;
6333
6334   unsigned long lit = 0L;
6335   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6336
6337   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6338   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6339   if(result)
6340     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6341   resolveIfx(&rIfx,ifx);
6342   lbl =  newiTempLabel(NULL);
6343   lbl_done =  newiTempLabel(NULL);
6344
6345
6346   /* if the left side is a literal or 
6347      if the right is in a pointer register and left 
6348      is not */
6349   if ((AOP_TYPE(left) == AOP_LIT) || 
6350       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6351     operand *t = right;
6352     right = left;
6353     left = t;
6354   }
6355   if(AOP_TYPE(right) == AOP_LIT)
6356     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6357
6358   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6359     preserve_result = 1;
6360
6361   if(result && !preserve_result)
6362     {
6363       int i;
6364       for(i = 0; i < AOP_SIZE(result); i++)
6365         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6366     }
6367
6368
6369   /* if the right side is a literal then anything goes */
6370   if (AOP_TYPE(right) == AOP_LIT &&
6371       AOP_TYPE(left) != AOP_DIR ) {
6372     switch(size) {
6373     case 2:
6374       genc16bit2lit(left, lit, 0);
6375       emitSKPZ;
6376       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6377       break;
6378     default:
6379       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6380       while (size--) {
6381         if(lit & 0xff) {
6382           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6383           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6384         } else {
6385           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6386         }
6387
6388         emitSKPZ;
6389         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6390         offset++;
6391         if(res_offset < res_size-1)
6392           res_offset++;
6393         lit >>= 8;
6394       }
6395       break;
6396     }
6397   }
6398
6399   /* if the right side is in a register or in direct space or
6400      if the left is a pointer register & right is not */    
6401   else if (AOP_TYPE(right) == AOP_REG ||
6402            AOP_TYPE(right) == AOP_DIR || 
6403            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6404            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6405     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6406     int lbl_key = lbl->key;
6407
6408     if(result) {
6409       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6410       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6411     }else {
6412       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6413       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6414               __FUNCTION__,__LINE__);
6415       return;
6416     }
6417    
6418 /*     switch(size) { */
6419 /*     case 2: */
6420 /*       genc16bit2lit(left, lit, 0); */
6421 /*       emitSKPNZ; */
6422 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6423 /*       break; */
6424 /*     default: */
6425     while (size--) {
6426       int emit_skip=1;
6427       if((AOP_TYPE(left) == AOP_DIR) && 
6428          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6429
6430         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6431         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6432
6433       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6434             
6435         switch (lit & 0xff) {
6436         case 0:
6437           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6438           break;
6439         case 1:
6440           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6441           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6442           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443           emit_skip=0;
6444           break;
6445         case 0xff:
6446           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6447           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6448           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6449           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6450           emit_skip=0;
6451           break;
6452         default:
6453           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6454           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6455         }
6456         lit >>= 8;
6457
6458       } else {
6459         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6460       }
6461       if(emit_skip) {
6462         if(AOP_TYPE(result) == AOP_CRY) {
6463           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6464           if(rIfx.condition)
6465             emitSKPNZ;
6466           else
6467             emitSKPZ;
6468           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6469         } else {
6470           /* fix me. probably need to check result size too */
6471           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6472           if(rIfx.condition)
6473             emitSKPZ;
6474           else
6475             emitSKPNZ;
6476           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6477           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6478         }
6479         if(ifx)
6480           ifx->generated=1;
6481       }
6482       emit_skip++;
6483       offset++;
6484       if(res_offset < res_size-1)
6485         res_offset++;
6486     }
6487 /*       break; */
6488 /*     } */
6489   } else if(AOP_TYPE(right) == AOP_REG &&
6490             AOP_TYPE(left) != AOP_DIR){
6491
6492     while(size--) {
6493       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6494       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6495       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6496       if(rIfx.condition)
6497         emitSKPNZ;
6498       else
6499         emitSKPZ;
6500       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6501       offset++;
6502       if(res_offset < res_size-1)
6503         res_offset++;
6504     }
6505       
6506   }else{
6507     /* right is a pointer reg need both a & b */
6508     while(size--) {
6509       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6510       if(strcmp(l,"b"))
6511         pic16_emitcode("mov","b,%s",l);
6512       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6513       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6514       offset++;
6515     }
6516   }
6517
6518   if(result && preserve_result)
6519     {
6520       int i;
6521       for(i = 0; i < AOP_SIZE(result); i++)
6522         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6523     }
6524
6525   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6526
6527   if(result && preserve_result)
6528     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6529
6530   if(!rIfx.condition)
6531     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6532
6533   pic16_emitpLabel(lbl->key);
6534
6535   if(result && preserve_result)
6536     {
6537       int i;
6538       for(i = 0; i < AOP_SIZE(result); i++)
6539         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6540
6541       pic16_emitpLabel(lbl_done->key);
6542    }
6543
6544   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6545
6546   if(ifx)
6547     ifx->generated = 1;
6548 }
6549 #endif
6550
6551 #if 0
6552 /*-----------------------------------------------------------------*/
6553 /* gencjne - compare and jump if not equal                         */
6554 /*-----------------------------------------------------------------*/
6555 static void gencjne(operand *left, operand *right, iCode *ifx)
6556 {
6557     symbol *tlbl  = newiTempLabel(NULL);
6558
6559     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6560     gencjneshort(left, right, lbl);
6561
6562     pic16_emitcode("mov","a,%s",one);
6563     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6564     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6565     pic16_emitcode("clr","a");
6566     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6567
6568     pic16_emitpLabel(lbl->key);
6569     pic16_emitpLabel(tlbl->key);
6570
6571 }
6572 #endif
6573
6574
6575 /*-----------------------------------------------------------------*/
6576 /* is_LitOp - check if operand has to be treated as literal        */
6577 /*-----------------------------------------------------------------*/
6578 static bool is_LitOp(operand *op)
6579 {
6580   return ((AOP_TYPE(op) == AOP_LIT)
6581       || ( (AOP_TYPE(op) == AOP_PCODE)
6582           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6583               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6584 }
6585
6586 /*-----------------------------------------------------------------*/
6587 /* is_LitAOp - check if operand has to be treated as literal        */
6588 /*-----------------------------------------------------------------*/
6589 static bool is_LitAOp(asmop *aop)
6590 {
6591   return ((aop->type == AOP_LIT)
6592       || ( (aop->type == AOP_PCODE)
6593           && ( (aop->aopu.pcop->type == PO_LITERAL)
6594               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6595 }
6596
6597
6598
6599 /*-----------------------------------------------------------------*/
6600 /* genCmpEq - generates code for equal to                          */
6601 /*-----------------------------------------------------------------*/
6602 static void genCmpEq (iCode *ic, iCode *ifx)
6603 {
6604   operand *left, *right, *result;
6605   symbol *falselbl = newiTempLabel(NULL);
6606   symbol *donelbl = newiTempLabel(NULL);
6607
6608   int preserve_result = 0;
6609   int generate_result = 0;
6610   int i=0;
6611   unsigned long lit = -1;
6612
6613   FENTRY;
6614   
6615   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6616   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6617   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6618  
6619   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6620
6621   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6622     {
6623       werror(W_POSSBUG2, __FILE__, __LINE__);
6624       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6625       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6626       goto release;
6627     }
6628
6629   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6630     {
6631       operand *tmp = right ;
6632       right = left;
6633       left = tmp;
6634     }
6635
6636   if (AOP_TYPE(right) == AOP_LIT) {
6637     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6638   }
6639
6640   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6641     preserve_result = 1;
6642
6643   if(result && AOP_SIZE(result))
6644     generate_result = 1;
6645
6646   if(generate_result && !preserve_result)
6647     {
6648       for(i = 0; i < AOP_SIZE(result); i++)
6649         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6650     }
6651
6652   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6653   for(i=0; i < AOP_SIZE(left); i++)
6654     {
6655       if(AOP_TYPE(left) != AOP_ACC)
6656         {
6657           if(is_LitOp(left))
6658             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6659           else
6660             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6661         }
6662       if(is_LitOp(right)) {
6663         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6664           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6665         }
6666       } else
6667         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6668
6669       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6670     }
6671
6672   // result == true
6673
6674   if(generate_result && preserve_result)
6675     {
6676       for(i = 0; i < AOP_SIZE(result); i++)
6677         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6678     }
6679
6680   if(generate_result)
6681     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6682
6683   if(generate_result && preserve_result)
6684     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6685
6686   if(ifx && IC_TRUE(ifx))
6687     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6688
6689   if(ifx && IC_FALSE(ifx))
6690     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6691
6692   pic16_emitpLabel(falselbl->key);
6693
6694   // result == false
6695
6696   if(ifx && IC_FALSE(ifx))
6697     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6698
6699   if(generate_result && preserve_result)
6700     {
6701       for(i = 0; i < AOP_SIZE(result); i++)
6702         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6703     }
6704
6705   pic16_emitpLabel(donelbl->key);
6706
6707   if(ifx)
6708     ifx->generated = 1;
6709
6710 release:
6711   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6712   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6713   pic16_freeAsmop(result,NULL,ic,TRUE);
6714
6715 }
6716
6717
6718 #if 0
6719 // old version kept for reference
6720
6721 /*-----------------------------------------------------------------*/
6722 /* genCmpEq - generates code for equal to                          */
6723 /*-----------------------------------------------------------------*/
6724 static void genCmpEq (iCode *ic, iCode *ifx)
6725 {
6726     operand *left, *right, *result;
6727     unsigned long lit = 0L;
6728     int size,offset=0;
6729     symbol *falselbl  = newiTempLabel(NULL);
6730
6731
6732     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6733
6734     if(ifx)
6735       DEBUGpic16_emitcode ("; ifx is non-null","");
6736     else
6737       DEBUGpic16_emitcode ("; ifx is null","");
6738
6739     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6740     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6741     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6742
6743     size = max(AOP_SIZE(left),AOP_SIZE(right));
6744
6745     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6746
6747     /* if literal, literal on the right or 
6748     if the right is in a pointer register and left 
6749     is not */
6750     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6751         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6752       operand *tmp = right ;
6753       right = left;
6754       left = tmp;
6755     }
6756
6757
6758     if(ifx && !AOP_SIZE(result)){
6759         symbol *tlbl;
6760         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6761         /* if they are both bit variables */
6762         if (AOP_TYPE(left) == AOP_CRY &&
6763             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6764                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6765             if(AOP_TYPE(right) == AOP_LIT){
6766                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6767                 if(lit == 0L){
6768                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6769                     pic16_emitcode("cpl","c");
6770                 } else if(lit == 1L) {
6771                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6772                 } else {
6773                     pic16_emitcode("clr","c");
6774                 }
6775                 /* AOP_TYPE(right) == AOP_CRY */
6776             } else {
6777                 symbol *lbl = newiTempLabel(NULL);
6778                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6779                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6780                 pic16_emitcode("cpl","c");
6781                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6782             }
6783             /* if true label then we jump if condition
6784             supplied is true */
6785             tlbl = newiTempLabel(NULL);
6786             if ( IC_TRUE(ifx) ) {
6787                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6788                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6789             } else {
6790                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6791                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6792             }
6793             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6794
6795                 {
6796                 /* left and right are both bit variables, result is carry */
6797                         resolvedIfx rIfx;
6798               
6799                         resolveIfx(&rIfx,ifx);
6800
6801                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6802                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6803                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6804                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6805                         genSkipz2(&rIfx,0);
6806                 }
6807         } else {
6808
6809                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6810
6811                         /* They're not both bit variables. Is the right a literal? */
6812                         if(AOP_TYPE(right) == AOP_LIT) {
6813                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6814             
6815                         switch(size) {
6816
6817                                 case 1:
6818                                         switch(lit & 0xff) {
6819                                                 case 1:
6820                                                                 if ( IC_TRUE(ifx) ) {
6821                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6822                                                                         emitSKPNZ;
6823                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6824                                                                 } else {
6825                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6826                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6827                                                                 }
6828                                                                 break;
6829                                                 case 0xff:
6830                                                                 if ( IC_TRUE(ifx) ) {
6831                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6832                                                                         emitSKPNZ;
6833                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6834                                                                 } else {
6835                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6836                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6837                                                                 }
6838                                                                 break;
6839                                                 default:
6840                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6841                                                                 if(lit)
6842                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6843                                                                 genSkip(ifx,'z');
6844                                         } // switch lit
6845
6846
6847                                         /* end of size == 1 */
6848                                         break;
6849               
6850                                 case 2:
6851                                         genc16bit2lit(left,lit,offset);
6852                                         genSkip(ifx,'z');
6853                                         break;
6854                                         /* end of size == 2 */
6855
6856                                 default:
6857                                         /* size is 4 */
6858                                         if(lit==0) {
6859                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6860                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6861                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6862                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6863                                                 genSkip(ifx,'z');
6864                                         } else {
6865                                                 /* search for patterns that can be optimized */
6866
6867                                                 genc16bit2lit(left,lit,0);
6868                                                 lit >>= 16;
6869                                                 if(lit) {
6870                                                                 if(IC_TRUE(ifx))
6871                                                                 emitSKPZ; // if hi word unequal
6872                                                                 else
6873                                                                 emitSKPNZ; // if hi word equal
6874                                                                 // fail early
6875                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6876                                                         genc16bit2lit(left,lit,2);
6877                                                         genSkip(ifx,'z');
6878                                                 } else {
6879                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6880                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6881                                                         genSkip(ifx,'z');
6882                                                 }
6883                                         }
6884                                                 pic16_emitpLabel(falselbl->key);
6885                                                 break;
6886
6887                         } // switch size
6888           
6889                         ifx->generated = 1;
6890                         goto release ;
6891             
6892
6893           } else if(AOP_TYPE(right) == AOP_CRY ) {
6894             /* we know the left is not a bit, but that the right is */
6895             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6896             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6897                       pic16_popGet(AOP(right),offset));
6898             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6899
6900             /* if the two are equal, then W will be 0 and the Z bit is set
6901              * we could test Z now, or go ahead and check the high order bytes if
6902              * the variable we're comparing is larger than a byte. */
6903
6904             while(--size)
6905               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6906
6907             if ( IC_TRUE(ifx) ) {
6908               emitSKPNZ;
6909               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6910               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6911             } else {
6912               emitSKPZ;
6913               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6914               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6915             }
6916
6917           } else {
6918             /* They're both variables that are larger than bits */
6919             int s = size;
6920
6921             tlbl = newiTempLabel(NULL);
6922
6923             while(size--) {
6924               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6925               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6926
6927               if ( IC_TRUE(ifx) ) {
6928                 if(size) {
6929                   emitSKPZ;
6930                 
6931                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6932
6933                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6934                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6935                 } else {
6936                   emitSKPNZ;
6937
6938                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6939
6940
6941                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6942                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6943                 }
6944               } else {
6945                 emitSKPZ;
6946
6947                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6948
6949                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6950                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6951               }
6952               offset++;
6953             }
6954             if(s>1 && IC_TRUE(ifx)) {
6955               pic16_emitpLabel(tlbl->key);
6956               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6957             }
6958           }
6959         }
6960         /* mark the icode as generated */
6961         ifx->generated = 1;
6962         goto release ;
6963     }
6964
6965     /* if they are both bit variables */
6966     if (AOP_TYPE(left) == AOP_CRY &&
6967         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6968         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6969         if(AOP_TYPE(right) == AOP_LIT){
6970             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6971             if(lit == 0L){
6972                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6973                 pic16_emitcode("cpl","c");
6974             } else if(lit == 1L) {
6975                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6976             } else {
6977                 pic16_emitcode("clr","c");
6978             }
6979             /* AOP_TYPE(right) == AOP_CRY */
6980         } else {
6981             symbol *lbl = newiTempLabel(NULL);
6982             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6983             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6984             pic16_emitcode("cpl","c");
6985             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6986         }
6987         /* c = 1 if egal */
6988         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6989             pic16_outBitC(result);
6990             goto release ;
6991         }
6992         if (ifx) {
6993             genIfxJump (ifx,"c");
6994             goto release ;
6995         }
6996         /* if the result is used in an arithmetic operation
6997         then put the result in place */
6998         pic16_outBitC(result);
6999     } else {
7000       
7001       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7002       gencjne(left,right,result,ifx);
7003 /*
7004       if(ifx) 
7005         gencjne(left,right,newiTempLabel(NULL));
7006       else {
7007         if(IC_TRUE(ifx)->key)
7008           gencjne(left,right,IC_TRUE(ifx)->key);
7009         else
7010           gencjne(left,right,IC_FALSE(ifx)->key);
7011         ifx->generated = 1;
7012         goto release ;
7013       }
7014       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7015         pic16_aopPut(AOP(result),"a",0);
7016         goto release ;
7017       }
7018
7019       if (ifx) {
7020         genIfxJump (ifx,"a");
7021         goto release ;
7022       }
7023 */
7024       /* if the result is used in an arithmetic operation
7025          then put the result in place */
7026 /*
7027       if (AOP_TYPE(result) != AOP_CRY) 
7028         pic16_outAcc(result);
7029 */
7030       /* leave the result in acc */
7031     }
7032
7033 release:
7034     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7035     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7036     pic16_freeAsmop(result,NULL,ic,TRUE);
7037 }
7038 #endif
7039
7040 /*-----------------------------------------------------------------*/
7041 /* ifxForOp - returns the icode containing the ifx for operand     */
7042 /*-----------------------------------------------------------------*/
7043 static iCode *ifxForOp ( operand *op, iCode *ic )
7044 {
7045   FENTRY2;
7046
7047     /* if true symbol then needs to be assigned */
7048     if (IS_TRUE_SYMOP(op))
7049         return NULL ;
7050
7051     /* if this has register type condition and
7052     the next instruction is ifx with the same operand
7053     and live to of the operand is upto the ifx only then */
7054     if (ic->next
7055         && ic->next->op == IFX
7056         && IC_COND(ic->next)->key == op->key
7057         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7058         ) {
7059                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7060           return ic->next;
7061     }
7062
7063     /*
7064     if (ic->next &&
7065         ic->next->op == IFX &&
7066         IC_COND(ic->next)->key == op->key) {
7067       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7068       return ic->next;
7069     }
7070     */
7071
7072     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7073     if (ic->next &&
7074         ic->next->op == IFX)
7075       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7076
7077     if (ic->next &&
7078         ic->next->op == IFX &&
7079         IC_COND(ic->next)->key == op->key) {
7080       DEBUGpic16_emitcode ("; "," key is okay");
7081       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7082                            OP_SYMBOL(op)->liveTo,
7083                            ic->next->seq);
7084     }
7085
7086 #if 0
7087     /* the code below is completely untested
7088      * it just allows ulong2fs.c compile -- VR */
7089          
7090     ic = ic->next;
7091     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7092                                         __FILE__, __FUNCTION__, __LINE__);
7093         
7094     /* if this has register type condition and
7095     the next instruction is ifx with the same operand
7096     and live to of the operand is upto the ifx only then */
7097     if (ic->next &&
7098         ic->next->op == IFX &&
7099         IC_COND(ic->next)->key == op->key &&
7100         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7101         return ic->next;
7102
7103     if (ic->next &&
7104         ic->next->op == IFX &&
7105         IC_COND(ic->next)->key == op->key) {
7106       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7107       return ic->next;
7108     }
7109
7110     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7111                                         __FILE__, __FUNCTION__, __LINE__);
7112
7113 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7114 #endif
7115
7116     return NULL;
7117 }
7118 /*-----------------------------------------------------------------*/
7119 /* genAndOp - for && operation                                     */
7120 /*-----------------------------------------------------------------*/
7121 static void genAndOp (iCode *ic)
7122 {
7123   operand *left,*right, *result;
7124 /*     symbol *tlbl; */
7125
7126     FENTRY;
7127
7128     /* note here that && operations that are in an
7129     if statement are taken away by backPatchLabels
7130     only those used in arthmetic operations remain */
7131     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7132     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7133     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7134
7135     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7136
7137     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7138     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7139     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7140
7141     /* if both are bit variables */
7142 /*     if (AOP_TYPE(left) == AOP_CRY && */
7143 /*         AOP_TYPE(right) == AOP_CRY ) { */
7144 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7145 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7146 /*         pic16_outBitC(result); */
7147 /*     } else { */
7148 /*         tlbl = newiTempLabel(NULL); */
7149 /*         pic16_toBoolean(left);     */
7150 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7151 /*         pic16_toBoolean(right); */
7152 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7153 /*         pic16_outBitAcc(result); */
7154 /*     } */
7155
7156     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7157     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7158     pic16_freeAsmop(result,NULL,ic,TRUE);
7159 }
7160
7161
7162 /*-----------------------------------------------------------------*/
7163 /* genOrOp - for || operation                                      */
7164 /*-----------------------------------------------------------------*/
7165 /*
7166   tsd pic port -
7167   modified this code, but it doesn't appear to ever get called
7168 */
7169
7170 static void genOrOp (iCode *ic)
7171 {
7172   operand *left,*right, *result;
7173   symbol *tlbl;
7174
7175     FENTRY;  
7176
7177   /* note here that || operations that are in an
7178     if statement are taken away by backPatchLabels
7179     only those used in arthmetic operations remain */
7180     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7181     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7182     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7183
7184     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7185
7186     /* if both are bit variables */
7187     if (AOP_TYPE(left) == AOP_CRY &&
7188         AOP_TYPE(right) == AOP_CRY ) {
7189       pic16_emitcode("clrc","");
7190       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7191                AOP(left)->aopu.aop_dir,
7192                AOP(left)->aopu.aop_dir);
7193       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7194                AOP(right)->aopu.aop_dir,
7195                AOP(right)->aopu.aop_dir);
7196       pic16_emitcode("setc","");
7197
7198     } else {
7199         tlbl = newiTempLabel(NULL);
7200         pic16_toBoolean(left);
7201         emitSKPZ;
7202         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7203         pic16_toBoolean(right);
7204         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7205
7206         pic16_outBitAcc(result);
7207     }
7208
7209     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7210     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7211     pic16_freeAsmop(result,NULL,ic,TRUE);            
7212 }
7213
7214 /*-----------------------------------------------------------------*/
7215 /* isLiteralBit - test if lit == 2^n                               */
7216 /*-----------------------------------------------------------------*/
7217 static int isLiteralBit(unsigned long lit)
7218 {
7219     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7220     0x100L,0x200L,0x400L,0x800L,
7221     0x1000L,0x2000L,0x4000L,0x8000L,
7222     0x10000L,0x20000L,0x40000L,0x80000L,
7223     0x100000L,0x200000L,0x400000L,0x800000L,
7224     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7225     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7226     int idx;
7227     
7228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7229     for(idx = 0; idx < 32; idx++)
7230         if(lit == pw[idx])
7231             return idx+1;
7232     return 0;
7233 }
7234
7235 /*-----------------------------------------------------------------*/
7236 /* continueIfTrue -                                                */
7237 /*-----------------------------------------------------------------*/
7238 static void continueIfTrue (iCode *ic)
7239 {
7240   FENTRY;
7241   if(IC_TRUE(ic))
7242     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7243   ic->generated = 1;
7244 }
7245
7246 /*-----------------------------------------------------------------*/
7247 /* jmpIfTrue -                                                     */
7248 /*-----------------------------------------------------------------*/
7249 static void jumpIfTrue (iCode *ic)
7250 {
7251   FENTRY;
7252   if(!IC_TRUE(ic))
7253     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7254   ic->generated = 1;
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* jmpTrueOrFalse -                                                */
7259 /*-----------------------------------------------------------------*/
7260 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7261 {
7262   // ugly but optimized by peephole
7263   FENTRY;
7264   if(IC_TRUE(ic)){
7265     symbol *nlbl = newiTempLabel(NULL);
7266       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7267       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7268       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7269       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7270   } else {
7271     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7272     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7273   }
7274   ic->generated = 1;
7275 }
7276
7277 /*-----------------------------------------------------------------*/
7278 /* genAnd  - code for and                                          */
7279 /*-----------------------------------------------------------------*/
7280 static void genAnd (iCode *ic, iCode *ifx)
7281 {
7282   operand *left, *right, *result;
7283   int size, offset=0;  
7284   unsigned long lit = 0L;
7285   int bytelit = 0;
7286   resolvedIfx rIfx;
7287
7288     FENTRY;
7289     
7290   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7291   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7292   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7293
7294   resolveIfx(&rIfx,ifx);
7295
7296   /* if left is a literal & right is not then exchange them */
7297   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7298       AOP_NEEDSACC(left)) {
7299     operand *tmp = right ;
7300     right = left;
7301     left = tmp;
7302   }
7303
7304   /* if result = right then exchange them */
7305   if(pic16_sameRegs(AOP(result),AOP(right))){
7306     operand *tmp = right ;
7307     right = left;
7308     left = tmp;
7309   }
7310
7311   /* if right is bit then exchange them */
7312   if (AOP_TYPE(right) == AOP_CRY &&
7313       AOP_TYPE(left) != AOP_CRY){
7314     operand *tmp = right ;
7315     right = left;
7316     left = tmp;
7317   }
7318   if(AOP_TYPE(right) == AOP_LIT)
7319     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7320
7321   size = AOP_SIZE(result);
7322
7323   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7324
7325   // if(bit & yy)
7326   // result = bit & yy;
7327   if (AOP_TYPE(left) == AOP_CRY){
7328     // c = bit & literal;
7329     if(AOP_TYPE(right) == AOP_LIT){
7330       if(lit & 1) {
7331         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7332           // no change
7333           goto release;
7334         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7335       } else {
7336         // bit(result) = 0;
7337         if(size && (AOP_TYPE(result) == AOP_CRY)){
7338           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7339           goto release;
7340         }
7341         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7342           jumpIfTrue(ifx);
7343           goto release;
7344         }
7345         pic16_emitcode("clr","c");
7346       }
7347     } else {
7348       if (AOP_TYPE(right) == AOP_CRY){
7349         // c = bit & bit;
7350         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7351         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7352       } else {
7353         // c = bit & val;
7354         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7355         // c = lsb
7356         pic16_emitcode("rrc","a");
7357         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7358       }
7359     }
7360     // bit = c
7361     // val = c
7362     if(size)
7363       pic16_outBitC(result);
7364     // if(bit & ...)
7365     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7366       genIfxJump(ifx, "c");           
7367     goto release ;
7368   }
7369
7370   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7371   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7372   if((AOP_TYPE(right) == AOP_LIT) &&
7373      (AOP_TYPE(result) == AOP_CRY) &&
7374      (AOP_TYPE(left) != AOP_CRY)){
7375     int posbit = isLiteralBit(lit);
7376     /* left &  2^n */
7377     if(posbit){
7378       posbit--;
7379       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7380       // bit = left & 2^n
7381       if(size)
7382         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7383       // if(left &  2^n)
7384       else{
7385         if(ifx){
7386 /*
7387           if(IC_TRUE(ifx)) {
7388             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7389             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7390           } else {
7391             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7392             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7393           }
7394 */
7395         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7396         size = AOP_SIZE(left);
7397
7398         {
7399           int bp = posbit, ofs=0;
7400           
7401             while(bp > 7) {
7402               bp -= 8;
7403               ofs++;
7404             }
7405
7406           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7407                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7408
7409         }
7410 /*
7411           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7412                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7413 */
7414           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7415           
7416           ifx->generated = 1;
7417         }
7418         goto release;
7419       }
7420     } else {
7421       symbol *tlbl = newiTempLabel(NULL);
7422       int sizel = AOP_SIZE(left);
7423
7424       if(size)
7425         emitSETC;
7426
7427       while(sizel--) {
7428         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7429
7430           /* patch provided by Aaron Colwell */
7431           if((posbit = isLiteralBit(bytelit)) != 0) {
7432               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7433                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7434                                                 (posbit-1),0, PO_GPR_REGISTER));
7435
7436               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7437 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7438           } else {
7439               if (bytelit == 0xff) {
7440                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7441                    * a peephole could optimize it out -- VR */
7442                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7443               } else {
7444                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7445                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7446               }
7447
7448               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7449                             pic16_popGetLabel(tlbl->key));
7450           }
7451         
7452 #if 0
7453           /* old code, left here for reference -- VR 09/2004 */
7454           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7455           // byte ==  2^n ?
7456           if((posbit = isLiteralBit(bytelit)) != 0)
7457             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7458           else{
7459             if(bytelit != 0x0FFL)
7460               pic16_emitcode("anl","a,%s",
7461                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7462             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7463           }
7464 #endif
7465         }
7466         offset++;
7467       }
7468       // bit = left & literal
7469       if(size) {
7470         emitCLRC;
7471         pic16_emitpLabel(tlbl->key);
7472       }
7473       // if(left & literal)
7474       else {
7475         if(ifx) {
7476           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7477           ifx->generated = 1;
7478         }
7479         pic16_emitpLabel(tlbl->key);
7480         goto release;
7481       }
7482     }
7483
7484     pic16_outBitC(result);
7485     goto release ;
7486   }
7487
7488   /* if left is same as result */
7489   if(pic16_sameRegs(AOP(result),AOP(left))){
7490     int know_W = -1;
7491     for(;size--; offset++,lit>>=8) {
7492       if(AOP_TYPE(right) == AOP_LIT){
7493         switch(lit & 0xff) {
7494         case 0x00:
7495           /*  and'ing with 0 has clears the result */
7496 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7497           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7498           break;
7499         case 0xff:
7500           /* and'ing with 0xff is a nop when the result and left are the same */
7501           break;
7502
7503         default:
7504           {
7505             int p = pic16_my_powof2( (~lit) & 0xff );
7506             if(p>=0) {
7507               /* only one bit is set in the literal, so use a bcf instruction */
7508 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7509               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7510
7511             } else {
7512               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7513               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7514               if(know_W != (lit&0xff))
7515                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7516               know_W = lit &0xff;
7517               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7518             }
7519           }    
7520         }
7521       } else {
7522         if (AOP_TYPE(left) == AOP_ACC) {
7523           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7524         } else {                    
7525           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7526           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7527
7528         }
7529       }
7530     }
7531
7532   } else {
7533     // left & result in different registers
7534     if(AOP_TYPE(result) == AOP_CRY){
7535       // result = bit
7536       // if(size), result in bit
7537       // if(!size && ifx), conditional oper: if(left & right)
7538       symbol *tlbl = newiTempLabel(NULL);
7539       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7540       if(size)
7541         pic16_emitcode("setb","c");
7542       while(sizer--){
7543         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7544         pic16_emitcode("anl","a,%s",
7545                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7546         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7547         offset++;
7548       }
7549       if(size){
7550         CLRC;
7551         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7552         pic16_outBitC(result);
7553       } else if(ifx)
7554         jmpTrueOrFalse(ifx, tlbl);
7555     } else {
7556       for(;(size--);offset++) {
7557         // normal case
7558         // result = left & right
7559         if(AOP_TYPE(right) == AOP_LIT){
7560           int t = (lit >> (offset*8)) & 0x0FFL;
7561           switch(t) { 
7562           case 0x00:
7563             pic16_emitcode("clrf","%s",
7564                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7565             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7566             break;
7567           case 0xff:
7568             pic16_emitcode("movf","%s,w",
7569                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7570             pic16_emitcode("movwf","%s",
7571                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7573             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7574             break;
7575           default:
7576             pic16_emitcode("movlw","0x%x",t);
7577             pic16_emitcode("andwf","%s,w",
7578                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7579             pic16_emitcode("movwf","%s",
7580                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7581               
7582             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7583             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7584             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7585           }
7586           continue;
7587         }
7588
7589         if (AOP_TYPE(left) == AOP_ACC) {
7590           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7591           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7592         } else {
7593           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7594           pic16_emitcode("andwf","%s,w",
7595                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7596           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7597           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7598         }
7599         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7600         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7601       }
7602     }
7603   }
7604
7605   release :
7606     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7607   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7608   pic16_freeAsmop(result,NULL,ic,TRUE);     
7609 }
7610
7611 /*-----------------------------------------------------------------*/
7612 /* genOr  - code for or                                            */
7613 /*-----------------------------------------------------------------*/
7614 static void genOr (iCode *ic, iCode *ifx)
7615 {
7616     operand *left, *right, *result;
7617     int size, offset=0;
7618     unsigned long lit = 0L;
7619
7620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7621
7622     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7623     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7624     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7625
7626     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7627
7628     /* if left is a literal & right is not then exchange them */
7629     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7630         AOP_NEEDSACC(left)) {
7631         operand *tmp = right ;
7632         right = left;
7633         left = tmp;
7634     }
7635
7636     /* if result = right then exchange them */
7637     if(pic16_sameRegs(AOP(result),AOP(right))){
7638         operand *tmp = right ;
7639         right = left;
7640         left = tmp;
7641     }
7642
7643     /* if right is bit then exchange them */
7644     if (AOP_TYPE(right) == AOP_CRY &&
7645         AOP_TYPE(left) != AOP_CRY){
7646         operand *tmp = right ;
7647         right = left;
7648         left = tmp;
7649     }
7650
7651     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7652
7653     if(AOP_TYPE(right) == AOP_LIT)
7654         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7655
7656     size = AOP_SIZE(result);
7657
7658     // if(bit | yy)
7659     // xx = bit | yy;
7660     if (AOP_TYPE(left) == AOP_CRY){
7661         if(AOP_TYPE(right) == AOP_LIT){
7662             // c = bit & literal;
7663             if(lit){
7664                 // lit != 0 => result = 1
7665                 if(AOP_TYPE(result) == AOP_CRY){
7666                   if(size)
7667                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7668                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7669                   //     AOP(result)->aopu.aop_dir,
7670                   //     AOP(result)->aopu.aop_dir);
7671                     else if(ifx)
7672                         continueIfTrue(ifx);
7673                     goto release;
7674                 }
7675             } else {
7676                 // lit == 0 => result = left
7677                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7678                     goto release;
7679                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7680             }
7681         } else {
7682             if (AOP_TYPE(right) == AOP_CRY){
7683               if(pic16_sameRegs(AOP(result),AOP(left))){
7684                 // c = bit | bit;
7685                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7686                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7687                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7688
7689                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7690                          AOP(result)->aopu.aop_dir,
7691                          AOP(result)->aopu.aop_dir);
7692                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7693                          AOP(right)->aopu.aop_dir,
7694                          AOP(right)->aopu.aop_dir);
7695                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7696                          AOP(result)->aopu.aop_dir,
7697                          AOP(result)->aopu.aop_dir);
7698               } else {
7699                 if( AOP_TYPE(result) == AOP_ACC) {
7700                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7701                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7702                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7703                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7704
7705                 } else {
7706
7707                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7708                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7709                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7710                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7711
7712                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7713                                  AOP(result)->aopu.aop_dir,
7714                                  AOP(result)->aopu.aop_dir);
7715                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7716                                  AOP(right)->aopu.aop_dir,
7717                                  AOP(right)->aopu.aop_dir);
7718                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7719                                  AOP(left)->aopu.aop_dir,
7720                                  AOP(left)->aopu.aop_dir);
7721                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7722                                  AOP(result)->aopu.aop_dir,
7723                                  AOP(result)->aopu.aop_dir);
7724                 }
7725               }
7726             } else {
7727                 // c = bit | val;
7728                 symbol *tlbl = newiTempLabel(NULL);
7729                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7730
7731
7732                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7733                 if( AOP_TYPE(right) == AOP_ACC) {
7734                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7735                   emitSKPNZ;
7736                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7737                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7738                 }
7739
7740
7741
7742                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7743                     pic16_emitcode(";XXX setb","c");
7744                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7745                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7746                 pic16_toBoolean(right);
7747                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7748                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7749                     jmpTrueOrFalse(ifx, tlbl);
7750                     goto release;
7751                 } else {
7752                     CLRC;
7753                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7754                 }
7755             }
7756         }
7757         // bit = c
7758         // val = c
7759         if(size)
7760             pic16_outBitC(result);
7761         // if(bit | ...)
7762         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7763             genIfxJump(ifx, "c");           
7764         goto release ;
7765     }
7766
7767     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7768     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7769     if((AOP_TYPE(right) == AOP_LIT) &&
7770        (AOP_TYPE(result) == AOP_CRY) &&
7771        (AOP_TYPE(left) != AOP_CRY)){
7772         if(lit){
7773           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7774             // result = 1
7775             if(size)
7776                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7777             else 
7778                 continueIfTrue(ifx);
7779             goto release;
7780         } else {
7781           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7782             // lit = 0, result = boolean(left)
7783             if(size)
7784                 pic16_emitcode(";XXX setb","c");
7785             pic16_toBoolean(right);
7786             if(size){
7787                 symbol *tlbl = newiTempLabel(NULL);
7788                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7789                 CLRC;
7790                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7791             } else {
7792                 genIfxJump (ifx,"a");
7793                 goto release;
7794             }
7795         }
7796         pic16_outBitC(result);
7797         goto release ;
7798     }
7799
7800     /* if left is same as result */
7801     if(pic16_sameRegs(AOP(result),AOP(left))){
7802       int know_W = -1;
7803       for(;size--; offset++,lit>>=8) {
7804         if(AOP_TYPE(right) == AOP_LIT){
7805           if((lit & 0xff) == 0)
7806             /*  or'ing with 0 has no effect */
7807             continue;
7808           else {
7809             int p = pic16_my_powof2(lit & 0xff);
7810             if(p>=0) {
7811               /* only one bit is set in the literal, so use a bsf instruction */
7812               pic16_emitpcode(POC_BSF,
7813                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7814             } else {
7815               if(know_W != (lit & 0xff))
7816                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7817               know_W = lit & 0xff;
7818               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7819             }
7820                     
7821           }
7822         } else {
7823           if (AOP_TYPE(left) == AOP_ACC) {
7824             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7825             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7826           } else {                  
7827             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7828             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7829
7830             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7831             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7832
7833           }
7834         }
7835       }
7836     } else {
7837         // left & result in different registers
7838         if(AOP_TYPE(result) == AOP_CRY){
7839             // result = bit
7840             // if(size), result in bit
7841             // if(!size && ifx), conditional oper: if(left | right)
7842             symbol *tlbl = newiTempLabel(NULL);
7843             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7844             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845
7846
7847             if(size)
7848                 pic16_emitcode(";XXX setb","c");
7849             while(sizer--){
7850                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7851                 pic16_emitcode(";XXX orl","a,%s",
7852                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7853                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7854                 offset++;
7855             }
7856             if(size){
7857                 CLRC;
7858                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7859                 pic16_outBitC(result);
7860             } else if(ifx)
7861                 jmpTrueOrFalse(ifx, tlbl);
7862         } else for(;(size--);offset++){
7863           // normal case
7864           // result = left & right
7865           if(AOP_TYPE(right) == AOP_LIT){
7866             int t = (lit >> (offset*8)) & 0x0FFL;
7867             switch(t) { 
7868             case 0x00:
7869               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7870               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7871
7872               pic16_emitcode("movf","%s,w",
7873                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7874               pic16_emitcode("movwf","%s",
7875                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7876               break;
7877             default:
7878               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7879               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7880               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7881
7882               pic16_emitcode("movlw","0x%x",t);
7883               pic16_emitcode("iorwf","%s,w",
7884                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7885               pic16_emitcode("movwf","%s",
7886                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7887               
7888             }
7889             continue;
7890           }
7891
7892           // faster than result <- left, anl result,right
7893           // and better if result is SFR
7894           if (AOP_TYPE(left) == AOP_ACC) {
7895             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7896             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897           } else {
7898             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7899             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7900
7901             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902             pic16_emitcode("iorwf","%s,w",
7903                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7904           }
7905           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7906           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7907         }
7908     }
7909
7910 release :
7911     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7912     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7913     pic16_freeAsmop(result,NULL,ic,TRUE);     
7914 }
7915
7916 /*-----------------------------------------------------------------*/
7917 /* genXor - code for xclusive or                                   */
7918 /*-----------------------------------------------------------------*/
7919 static void genXor (iCode *ic, iCode *ifx)
7920 {
7921   operand *left, *right, *result;
7922   int size, offset=0;
7923   unsigned long lit = 0L;
7924
7925   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7926
7927   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7928   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7929   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7930
7931   /* if left is a literal & right is not ||
7932      if left needs acc & right does not */
7933   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7934       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7935     operand *tmp = right ;
7936     right = left;
7937     left = tmp;
7938   }
7939
7940   /* if result = right then exchange them */
7941   if(pic16_sameRegs(AOP(result),AOP(right))){
7942     operand *tmp = right ;
7943     right = left;
7944     left = tmp;
7945   }
7946
7947   /* if right is bit then exchange them */
7948   if (AOP_TYPE(right) == AOP_CRY &&
7949       AOP_TYPE(left) != AOP_CRY){
7950     operand *tmp = right ;
7951     right = left;
7952     left = tmp;
7953   }
7954   if(AOP_TYPE(right) == AOP_LIT)
7955     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7956
7957   size = AOP_SIZE(result);
7958
7959   // if(bit ^ yy)
7960   // xx = bit ^ yy;
7961   if (AOP_TYPE(left) == AOP_CRY){
7962     if(AOP_TYPE(right) == AOP_LIT){
7963       // c = bit & literal;
7964       if(lit>>1){
7965         // lit>>1  != 0 => result = 1
7966         if(AOP_TYPE(result) == AOP_CRY){
7967           if(size)
7968             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7969             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7970           else if(ifx)
7971             continueIfTrue(ifx);
7972           goto release;
7973         }
7974         pic16_emitcode("setb","c");
7975       } else{
7976         // lit == (0 or 1)
7977         if(lit == 0){
7978           // lit == 0, result = left
7979           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7980             goto release;
7981           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7982         } else{
7983           // lit == 1, result = not(left)
7984           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7985             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7986             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7987             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7988             goto release;
7989           } else {
7990             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7991             pic16_emitcode("cpl","c");
7992           }
7993         }
7994       }
7995
7996     } else {
7997       // right != literal
7998       symbol *tlbl = newiTempLabel(NULL);
7999       if (AOP_TYPE(right) == AOP_CRY){
8000         // c = bit ^ bit;
8001         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8002       }
8003       else{
8004         int sizer = AOP_SIZE(right);
8005         // c = bit ^ val
8006         // if val>>1 != 0, result = 1
8007         pic16_emitcode("setb","c");
8008         while(sizer){
8009           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8010           if(sizer == 1)
8011             // test the msb of the lsb
8012             pic16_emitcode("anl","a,#0xfe");
8013           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8014           sizer--;
8015         }
8016         // val = (0,1)
8017         pic16_emitcode("rrc","a");
8018       }
8019       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8020       pic16_emitcode("cpl","c");
8021       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8022     }
8023     // bit = c
8024     // val = c
8025     if(size)
8026       pic16_outBitC(result);
8027     // if(bit | ...)
8028     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8029       genIfxJump(ifx, "c");           
8030     goto release ;
8031   }
8032
8033   if(pic16_sameRegs(AOP(result),AOP(left))){
8034     /* if left is same as result */
8035     for(;size--; offset++) {
8036       if(AOP_TYPE(right) == AOP_LIT){
8037         int t  = (lit >> (offset*8)) & 0x0FFL;
8038         if(t == 0x00L)
8039           continue;
8040         else
8041           if (IS_AOP_PREG(left)) {
8042             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8043             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8044             pic16_aopPut(AOP(result),"a",offset);
8045           } else {
8046             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8047             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8048             pic16_emitcode("xrl","%s,%s",
8049                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8050                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8051           }
8052       } else {
8053         if (AOP_TYPE(left) == AOP_ACC)
8054           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8055         else {
8056           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8057           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8058 /*
8059           if (IS_AOP_PREG(left)) {
8060             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8061             pic16_aopPut(AOP(result),"a",offset);
8062           } else
8063             pic16_emitcode("xrl","%s,a",
8064                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8065 */
8066         }
8067       }
8068     }
8069   } else {
8070     // left & result in different registers
8071     if(AOP_TYPE(result) == AOP_CRY){
8072       // result = bit
8073       // if(size), result in bit
8074       // if(!size && ifx), conditional oper: if(left ^ right)
8075       symbol *tlbl = newiTempLabel(NULL);
8076       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8077       if(size)
8078         pic16_emitcode("setb","c");
8079       while(sizer--){
8080         if((AOP_TYPE(right) == AOP_LIT) &&
8081            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8082           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8083         } else {
8084           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8085           pic16_emitcode("xrl","a,%s",
8086                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8087         }
8088         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8089         offset++;
8090       }
8091       if(size){
8092         CLRC;
8093         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8094         pic16_outBitC(result);
8095       } else if(ifx)
8096         jmpTrueOrFalse(ifx, tlbl);
8097     } else for(;(size--);offset++){
8098       // normal case
8099       // result = left & right
8100       if(AOP_TYPE(right) == AOP_LIT){
8101         int t = (lit >> (offset*8)) & 0x0FFL;
8102         switch(t) { 
8103         case 0x00:
8104           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8105           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8106           pic16_emitcode("movf","%s,w",
8107                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8108           pic16_emitcode("movwf","%s",
8109                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8110           break;
8111         case 0xff:
8112           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8113           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8114           pic16_emitcode("comf","%s,w",
8115                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8116           pic16_emitcode("movwf","%s",
8117                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8118           break;
8119         default:
8120           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8121           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8122           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8123           pic16_emitcode("movlw","0x%x",t);
8124           pic16_emitcode("xorwf","%s,w",
8125                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8126           pic16_emitcode("movwf","%s",
8127                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8128
8129         }
8130         continue;
8131       }
8132
8133       // faster than result <- left, anl result,right
8134       // and better if result is SFR
8135       if (AOP_TYPE(left) == AOP_ACC) {
8136         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8137         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8138       } else {
8139         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8140         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8141         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8142         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8143       }
8144       if ( AOP_TYPE(result) != AOP_ACC){
8145         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8146         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8147       }
8148     }
8149   }
8150
8151   release :
8152     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8153   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8154   pic16_freeAsmop(result,NULL,ic,TRUE);     
8155 }
8156
8157 /*-----------------------------------------------------------------*/
8158 /* genInline - write the inline code out                           */
8159 /*-----------------------------------------------------------------*/
8160 static void genInline (iCode *ic)
8161 {
8162   char *buffer, *bp, *bp1;
8163     
8164         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8165
8166         _G.inLine += (!options.asmpeep);
8167
8168         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8169         strcpy(buffer,IC_INLINE(ic));
8170         
8171         while((bp1=strstr(bp, "\\n"))) {
8172           *bp1++ = '\n';
8173           *bp1++ = ' ';
8174           bp = bp1;
8175         }
8176         bp = bp1 = buffer;
8177
8178 #if 0
8179   /* This is an experimental code for #pragma inline
8180      and is temporarily disabled for 2.5.0 release */
8181         if(asmInlineMap)
8182         {
8183           symbol *sym;
8184           char *s;
8185           char *cbuf;
8186           int cblen;
8187
8188             cbuf = Safe_strdup(buffer);
8189             cblen = strlen(buffer)+1;
8190             memset(cbuf, 0, cblen);
8191
8192             bp = buffer;
8193             bp1 = cbuf;
8194             while(*bp) {
8195               if(*bp != '%')*bp1++ = *bp++;
8196               else {
8197                 int i;
8198
8199                   bp++;
8200                   i = *bp - '0';
8201                   if(i>elementsInSet(asmInlineMap))break;
8202                   
8203                   bp++;
8204                   s = indexSet(asmInlineMap, i);
8205                   DEBUGpc("searching symbol s = `%s'", s);
8206                   sym = findSym(SymbolTab, NULL, s);
8207
8208                   if(sym->reqv) {
8209                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8210                   } else {
8211                     strcat(bp1, sym->rname);
8212                   }
8213                   
8214                   while(*bp1)bp1++;
8215               }
8216               
8217               if(strlen(bp1) > cblen - 16) {
8218                 int i = strlen(cbuf);
8219                 cblen += 50;
8220                 cbuf = realloc(cbuf, cblen);
8221                 memset(cbuf+i, 0, 50);
8222                 bp1 = cbuf + i;
8223               }
8224             }
8225             
8226             free(buffer);
8227             buffer = Safe_strdup( cbuf );
8228             free(cbuf);
8229             
8230             bp = bp1 = buffer;
8231         }
8232 #endif  /* 0 */
8233
8234         /* emit each line as a code */
8235         while (*bp) {
8236                 if (*bp == '\n') {
8237                         *bp++ = '\0';
8238
8239                         if(*bp1)
8240                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8241                         bp1 = bp;
8242                 } else {
8243                         if (*bp == ':') {
8244                                 bp++;
8245                                 *bp = '\0';
8246                                 bp++;
8247
8248                                 /* print label, use this special format with NULL directive
8249                                  * to denote that the argument should not be indented with tab */
8250                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8251                                 bp1 = bp;
8252                         } if (*bp == ';') {
8253                                 /* advance to end of line (prevent splitting of comments at ':' */
8254                                 while (*bp && *bp != '\n') {
8255                                         bp++;
8256                                 } // while
8257                         } else
8258                                 bp++;
8259                 }
8260         }
8261
8262         if ((bp1 != bp) && *bp1)
8263                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8264
8265
8266     Safe_free(buffer);
8267
8268     _G.inLine -= (!options.asmpeep);
8269 }
8270
8271 /*-----------------------------------------------------------------*/
8272 /* genRRC - rotate right with carry                                */
8273 /*-----------------------------------------------------------------*/
8274 static void genRRC (iCode *ic)
8275 {
8276   operand *left , *result ;
8277   int size, offset = 0, same;
8278
8279   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8280
8281   /* rotate right with carry */
8282   left = IC_LEFT(ic);
8283   result=IC_RESULT(ic);
8284   pic16_aopOp (left,ic,FALSE);
8285   pic16_aopOp (result,ic,TRUE);
8286
8287   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8288
8289   same = pic16_sameRegs(AOP(result),AOP(left));
8290
8291   size = AOP_SIZE(result);    
8292
8293   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8294
8295   /* get the lsb and put it into the carry */
8296   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8297
8298   offset = 0 ;
8299
8300   while(size--) {
8301
8302     if(same) {
8303       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8304     } else {
8305       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8306       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8307     }
8308
8309     offset++;
8310   }
8311
8312   pic16_freeAsmop(left,NULL,ic,TRUE);
8313   pic16_freeAsmop(result,NULL,ic,TRUE);
8314 }
8315
8316 /*-----------------------------------------------------------------*/
8317 /* genRLC - generate code for rotate left with carry               */
8318 /*-----------------------------------------------------------------*/
8319 static void genRLC (iCode *ic)
8320 {    
8321   operand *left , *result ;
8322   int size, offset = 0;
8323   int same;
8324
8325   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8326   /* rotate right with carry */
8327   left = IC_LEFT(ic);
8328   result=IC_RESULT(ic);
8329   pic16_aopOp (left,ic,FALSE);
8330   pic16_aopOp (result,ic,TRUE);
8331
8332   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8333
8334   same = pic16_sameRegs(AOP(result),AOP(left));
8335
8336   /* move it to the result */
8337   size = AOP_SIZE(result);    
8338
8339   /* get the msb and put it into the carry */
8340   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8341
8342   offset = 0 ;
8343
8344   while(size--) {
8345
8346     if(same) {
8347       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8348     } else {
8349       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8350       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8351     }
8352
8353     offset++;
8354   }
8355
8356
8357   pic16_freeAsmop(left,NULL,ic,TRUE);
8358   pic16_freeAsmop(result,NULL,ic,TRUE);
8359 }
8360
8361
8362 /* gpasm can get the highest order bit with HIGH/UPPER
8363  * so the following probably is not needed -- VR */
8364  
8365 /*-----------------------------------------------------------------*/
8366 /* genGetHbit - generates code get highest order bit               */
8367 /*-----------------------------------------------------------------*/
8368 static void genGetHbit (iCode *ic)
8369 {
8370     operand *left, *result;
8371     left = IC_LEFT(ic);
8372     result=IC_RESULT(ic);
8373     pic16_aopOp (left,ic,FALSE);
8374     pic16_aopOp (result,ic,FALSE);
8375
8376     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8377     /* get the highest order byte into a */
8378     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8379     if(AOP_TYPE(result) == AOP_CRY){
8380         pic16_emitcode("rlc","a");
8381         pic16_outBitC(result);
8382     }
8383     else{
8384         pic16_emitcode("rl","a");
8385         pic16_emitcode("anl","a,#0x01");
8386         pic16_outAcc(result);
8387     }
8388
8389
8390     pic16_freeAsmop(left,NULL,ic,TRUE);
8391     pic16_freeAsmop(result,NULL,ic,TRUE);
8392 }
8393
8394 #if 0
8395 /*-----------------------------------------------------------------*/
8396 /* AccRol - rotate left accumulator by known count                 */
8397 /*-----------------------------------------------------------------*/
8398 static void AccRol (int shCount)
8399 {
8400     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8401     shCount &= 0x0007;              // shCount : 0..7
8402     switch(shCount){
8403         case 0 :
8404             break;
8405         case 1 :
8406             pic16_emitcode("rl","a");
8407             break;
8408         case 2 :
8409             pic16_emitcode("rl","a");
8410             pic16_emitcode("rl","a");
8411             break;
8412         case 3 :
8413             pic16_emitcode("swap","a");
8414             pic16_emitcode("rr","a");
8415             break;
8416         case 4 :
8417             pic16_emitcode("swap","a");
8418             break;
8419         case 5 :
8420             pic16_emitcode("swap","a");
8421             pic16_emitcode("rl","a");
8422             break;
8423         case 6 :
8424             pic16_emitcode("rr","a");
8425             pic16_emitcode("rr","a");
8426             break;
8427         case 7 :
8428             pic16_emitcode("rr","a");
8429             break;
8430     }
8431 }
8432 #endif
8433
8434 /*-----------------------------------------------------------------*/
8435 /* AccLsh - left shift accumulator by known count                  */
8436 /*-----------------------------------------------------------------*/
8437 static void AccLsh (int shCount, int doMask)
8438 {
8439         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8440         switch(shCount){
8441                 case 0 :
8442                         return;
8443                         break;
8444                 case 1 :
8445                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8446                         break;
8447                 case 2 :
8448                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8450                         break;
8451                 case 3 :
8452                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8453                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8454                         break;
8455                 case 4 :
8456                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8457                         break;
8458                 case 5 :
8459                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8460                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8461                         break;
8462                 case 6 :
8463                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8465                         break;
8466                 case 7 :
8467                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8468                         break;
8469         }
8470         if (doMask) {
8471                 /* no masking is required in genPackBits */
8472                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8473         }
8474 }
8475
8476 /*-----------------------------------------------------------------*/
8477 /* AccRsh - right shift accumulator by known count                 */
8478 /*-----------------------------------------------------------------*/
8479 static void AccRsh (int shCount, int andmask)
8480 {
8481         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8482         switch(shCount){
8483                 case 0 :
8484                         return; break;
8485                 case 1 :
8486                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487                         break;
8488                 case 2 :
8489                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8490                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8491                         break;
8492                 case 3 :
8493                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8494                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8495                         break;
8496                 case 4 :
8497                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8498                         break;
8499                 case 5 :
8500                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8501                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502                         break;
8503                 case 6 :
8504                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8505                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8506                         break;
8507                 case 7 :
8508                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8509                         break;
8510         }
8511         
8512         if(andmask)
8513                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8514         else
8515                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8516 }
8517
8518 #if 0
8519 /*-----------------------------------------------------------------*/
8520 /* AccSRsh - signed right shift accumulator by known count                 */
8521 /*-----------------------------------------------------------------*/
8522 static void AccSRsh (int shCount)
8523 {
8524     symbol *tlbl ;
8525     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8526     if(shCount != 0){
8527         if(shCount == 1){
8528             pic16_emitcode("mov","c,acc.7");
8529             pic16_emitcode("rrc","a");
8530         } else if(shCount == 2){
8531             pic16_emitcode("mov","c,acc.7");
8532             pic16_emitcode("rrc","a");
8533             pic16_emitcode("mov","c,acc.7");
8534             pic16_emitcode("rrc","a");
8535         } else {
8536             tlbl = newiTempLabel(NULL);
8537             /* rotate right accumulator */
8538             AccRol(8 - shCount);
8539             /* and kill the higher order bits */
8540             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8541             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8542             pic16_emitcode("orl","a,#0x%02x",
8543                      (unsigned char)~SRMask[shCount]);
8544             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8545         }
8546     }
8547 }
8548 #endif
8549
8550 /*-----------------------------------------------------------------*/
8551 /* shiftR1Left2Result - shift right one byte from left to result   */
8552 /*-----------------------------------------------------------------*/
8553 static void shiftR1Left2ResultSigned (operand *left, int offl,
8554                                 operand *result, int offr,
8555                                 int shCount)
8556 {
8557   int same;
8558
8559   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8560
8561   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8562
8563   switch(shCount) {
8564   case 1:
8565     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8566     if(same) 
8567       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8568     else {
8569       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8570       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8571     }
8572
8573     break;
8574   case 2:
8575
8576     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8577     if(same) 
8578       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8579     else {
8580       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8581       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8582     }
8583     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8584     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8585
8586     break;
8587
8588   case 3:
8589     if(same)
8590       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8591     else {
8592       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8593       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8594     }
8595
8596     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8597     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8598     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8599
8600     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8601     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8602
8603     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8604     break;
8605
8606   case 4:
8607     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8608     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8609     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8610     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8611     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8612     break;
8613   case 5:
8614     if(same) {
8615       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8616     } else {
8617       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8618       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8619     }
8620     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8621     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8622     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8623     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8624     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8625     break;
8626
8627   case 6:
8628     if(same) {
8629       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8630       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8631       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8632       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8633       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8634       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8635     } else {
8636       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8637       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8638       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8639       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8640       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8641     }
8642     break;
8643
8644   case 7:
8645     if(same) {
8646       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8647       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8648       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8649       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8650     } else {
8651       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8652       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8653       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8654     }
8655
8656   default:
8657     break;
8658   }
8659 }
8660
8661 /*-----------------------------------------------------------------*/
8662 /* shiftR1Left2Result - shift right one byte from left to result   */
8663 /*-----------------------------------------------------------------*/
8664 static void shiftR1Left2Result (operand *left, int offl,
8665                                 operand *result, int offr,
8666                                 int shCount, int sign)
8667 {
8668   int same;
8669
8670   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8671
8672   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8673
8674   /* Copy the msb into the carry if signed. */
8675   if(sign) {
8676     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8677     return;
8678   }
8679
8680
8681
8682   switch(shCount) {
8683   case 1:
8684     emitCLRC;
8685     if(same) 
8686       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8687     else {
8688       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8689       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690     }
8691     break;
8692   case 2:
8693     emitCLRC;
8694     if(same) {
8695       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8696     } else {
8697       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8698       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8699     }
8700     emitCLRC;
8701     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8702
8703     break;
8704   case 3:
8705     if(same)
8706       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8707     else {
8708       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8710     }
8711
8712     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8713     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8714     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8715     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8716     break;
8717       
8718   case 4:
8719     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8720     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8721     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8722     break;
8723
8724   case 5:
8725     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8726     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8727     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8728     //emitCLRC;
8729     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8730
8731     break;
8732   case 6:
8733
8734     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8735     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8736     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8737     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8738     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8739     break;
8740
8741   case 7:
8742
8743     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8744     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8745     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8746
8747     break;
8748
8749   default:
8750     break;
8751   }
8752 }
8753
8754 /*-----------------------------------------------------------------*/
8755 /* shiftL1Left2Result - shift left one byte from left to result    */
8756 /*-----------------------------------------------------------------*/
8757 static void shiftL1Left2Result (operand *left, int offl,
8758                                 operand *result, int offr, int shCount)
8759 {
8760   int same;
8761
8762   //    char *l;
8763   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8764
8765   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8766   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8767     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8768     //    MOVA(l);
8769     /* shift left accumulator */
8770     //AccLsh(shCount, 1); // don't comment out just yet...
8771   //    pic16_aopPut(AOP(result),"a",offr);
8772
8773   switch(shCount) {
8774   case 1:
8775     /* Shift left 1 bit position */
8776     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8777     if(same) {
8778       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8779     } else {
8780       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8781       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782     }
8783     break;
8784   case 2:
8785     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8786     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8787     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8788     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8789     break;
8790   case 3:
8791     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8792     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8793     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8794     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8795     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8796     break;
8797   case 4:
8798     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8799     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8800     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8801     break;
8802   case 5:
8803     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8804     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8805     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8806     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8807     break;
8808   case 6:
8809     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8810     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8811     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8812     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8813     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8814     break;
8815   case 7:
8816     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8817     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8818     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8819     break;
8820
8821   default:
8822     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8823   }
8824
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* movLeft2Result - move byte from left to result                  */
8829 /*-----------------------------------------------------------------*/
8830 static void movLeft2Result (operand *left, int offl,
8831                             operand *result, int offr)
8832 {
8833   char *l;
8834   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8835   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8836     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8837
8838     if (*l == '@' && (IS_AOP_PREG(result))) {
8839       pic16_emitcode("mov","a,%s",l);
8840       pic16_aopPut(AOP(result),"a",offr);
8841     } else {
8842       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8843       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8844     }
8845   }
8846 }
8847
8848 /*-----------------------------------------------------------------*/
8849 /* shiftL2Left2Result - shift left two bytes from left to result   */
8850 /*-----------------------------------------------------------------*/
8851 static void shiftL2Left2Result (operand *left, int offl,
8852                                 operand *result, int offr, int shCount)
8853 {
8854   int same = pic16_sameRegs(AOP(result), AOP(left));
8855   int i;
8856
8857   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8858
8859   if (same && (offl != offr)) { // shift bytes
8860     if (offr > offl) {
8861        for(i=1;i>-1;i--) {
8862          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8863          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8864        }
8865     } else { // just treat as different later on
8866                 same = 0;
8867     }
8868   }
8869
8870   if(same) {
8871     switch(shCount) {
8872     case 0:
8873       break;
8874     case 1:
8875     case 2:
8876     case 3:
8877
8878       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8879       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8880       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8881
8882       while(--shCount) {
8883                 emitCLRC;
8884                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8885                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8886       }
8887
8888       break;
8889     case 4:
8890     case 5:
8891       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8892       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8893       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8894       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8895       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8896       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8897       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8898       if(shCount >=5) {
8899                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8900                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8901       }
8902       break;
8903     case 6:
8904       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8905       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8906       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8907       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8909       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8910       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8911       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8912       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8913       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8914       break;
8915     case 7:
8916       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8917       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8918       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8919       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8920       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8921     }
8922
8923   } else {
8924     switch(shCount) {
8925     case 0:
8926       break;
8927     case 1:
8928     case 2:
8929     case 3:
8930       /* note, use a mov/add for the shift since the mov has a
8931          chance of getting optimized out */
8932       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8933       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8934       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8935       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8936       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8937
8938       while(--shCount) {
8939                 emitCLRC;
8940                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8941                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8942       }
8943       break;
8944
8945     case 4:
8946     case 5:
8947       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8948       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8949       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8950       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8951       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8952       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8953       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8955
8956
8957       if(shCount == 5) {
8958                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8960       }
8961       break;
8962     case 6:
8963       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8964       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8965       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8966       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8967
8968       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8972       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8976       break;
8977     case 7:
8978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8979       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8980       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8981       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983     }
8984   }
8985
8986 }
8987 /*-----------------------------------------------------------------*/
8988 /* shiftR2Left2Result - shift right two bytes from left to result  */
8989 /*-----------------------------------------------------------------*/
8990 static void shiftR2Left2Result (operand *left, int offl,
8991                                 operand *result, int offr,
8992                                 int shCount, int sign)
8993 {
8994   int same = pic16_sameRegs(AOP(result), AOP(left));
8995   int i;
8996   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8997
8998   if (same && (offl != offr)) { // shift right bytes
8999     if (offr < offl) {
9000        for(i=0;i<2;i++) {
9001          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9002          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9003        }
9004     } else { // just treat as different later on
9005                 same = 0;
9006     }
9007   }
9008
9009   switch(shCount) {
9010   case 0:
9011     break;
9012   case 1:
9013   case 2:
9014   case 3:
9015     if(sign)
9016       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9017     else
9018       emitCLRC;
9019
9020     if(same) {
9021       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9022       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9023     } else {
9024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9025       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9026       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9027       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9028     }
9029
9030     while(--shCount) {
9031       if(sign)
9032                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9033       else
9034                 emitCLRC;
9035       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9036       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9037     }
9038     break;
9039   case 4:
9040   case 5:
9041     if(same) {
9042
9043       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9044       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9046
9047       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9048       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9049       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9050       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9051     } else {
9052       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9053       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9054       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9055
9056       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9057       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9058       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9059       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9060       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9061     }
9062
9063     if(shCount >=5) {
9064       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9065       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9066     }
9067
9068     if(sign) {
9069       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9070       pic16_emitpcode(POC_BTFSC, 
9071                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9072       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9073     }
9074
9075     break;
9076
9077   case 6:
9078     if(same) {
9079
9080       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9081       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9082
9083       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9084       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9085       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9086       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9087       if(sign) {
9088         pic16_emitpcode(POC_BTFSC, 
9089                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9090         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9091       }
9092       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9093       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9094       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9095       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9096     } else {
9097       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9098       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9099       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9101       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9103       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9104       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9105       if(sign) {
9106         pic16_emitpcode(POC_BTFSC, 
9107                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9108         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9109       }
9110       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9111       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9112
9113         
9114     }
9115
9116     break;
9117   case 7:
9118     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9119     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9120     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9122     if(sign) {
9123       emitSKPNC;
9124       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9125     } else 
9126       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9127   }
9128 }
9129
9130
9131 /*-----------------------------------------------------------------*/
9132 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9133 /*-----------------------------------------------------------------*/
9134 static void shiftLLeftOrResult (operand *left, int offl,
9135                                 operand *result, int offr, int shCount)
9136 {
9137     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9138
9139     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9140     /* shift left accumulator */
9141     AccLsh(shCount, 1);
9142     /* or with result */
9143     /* back to result */
9144     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9145 }
9146
9147 /*-----------------------------------------------------------------*/
9148 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9149 /*-----------------------------------------------------------------*/
9150 static void shiftRLeftOrResult (operand *left, int offl,
9151                                 operand *result, int offr, int shCount)
9152 {
9153     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9154     
9155     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9156     /* shift right accumulator */
9157     AccRsh(shCount, 1);
9158     /* or with result */
9159     /* back to result */
9160     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9161 }
9162
9163 /*-----------------------------------------------------------------*/
9164 /* genlshOne - left shift a one byte quantity by known count       */
9165 /*-----------------------------------------------------------------*/
9166 static void genlshOne (operand *result, operand *left, int shCount)
9167 {       
9168     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9169     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9170 }
9171
9172 /*-----------------------------------------------------------------*/
9173 /* genlshTwo - left shift two bytes by known amount != 0           */
9174 /*-----------------------------------------------------------------*/
9175 static void genlshTwo (operand *result,operand *left, int shCount)
9176 {
9177     int size;
9178     
9179     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9180     size = pic16_getDataSize(result);
9181
9182     /* if shCount >= 8 */
9183     if (shCount >= 8) {
9184         shCount -= 8 ;
9185
9186         if (size > 1){
9187             if (shCount)
9188                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9189             else 
9190                 movLeft2Result(left, LSB, result, MSB16);
9191         }
9192         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9193     }
9194
9195     /*  1 <= shCount <= 7 */
9196     else {  
9197         if(size == 1)
9198             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9199         else 
9200             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9201     }
9202 }
9203
9204 /*-----------------------------------------------------------------*/
9205 /* shiftLLong - shift left one long from left to result            */
9206 /* offr = LSB or MSB16                                             */
9207 /*-----------------------------------------------------------------*/
9208 static void shiftLLong (operand *left, operand *result, int offr )
9209 {
9210     int size = AOP_SIZE(result);
9211     int same = pic16_sameRegs(AOP(left),AOP(result));
9212         int i;
9213
9214     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9215
9216         if (same && (offr == MSB16)) { //shift one byte
9217                 for(i=size-1;i>=MSB16;i--) {
9218                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9219                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9220                 }
9221         } else {
9222                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9223         }
9224         
9225     if (size > LSB+offr ){
9226                 if (same) {
9227                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9228                 } else {
9229                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9230                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9231                 }
9232          }
9233
9234     if(size > MSB16+offr){
9235                 if (same) {
9236                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9237                 } else {
9238                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9239                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9240                 }
9241     }
9242
9243     if(size > MSB24+offr){
9244                 if (same) {
9245                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9246                 } else {
9247                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9248                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9249                 }
9250     }
9251
9252     if(size > MSB32+offr){
9253                 if (same) {
9254                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9255                 } else {
9256                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9257                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9258                 }
9259     }
9260     if(offr != LSB)
9261                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9262
9263 }
9264
9265 /*-----------------------------------------------------------------*/
9266 /* genlshFour - shift four byte by a known amount != 0             */
9267 /*-----------------------------------------------------------------*/
9268 static void genlshFour (operand *result, operand *left, int shCount)
9269 {
9270     int size;
9271
9272     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9273     size = AOP_SIZE(result);
9274
9275     /* if shifting more that 3 bytes */
9276     if (shCount >= 24 ) {
9277         shCount -= 24;
9278         if (shCount)
9279             /* lowest order of left goes to the highest
9280             order of the destination */
9281             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9282         else
9283             movLeft2Result(left, LSB, result, MSB32);
9284
9285                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9286                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9287                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9288
9289         return;
9290     }
9291
9292     /* more than two bytes */
9293     else if ( shCount >= 16 ) {
9294         /* lower order two bytes goes to higher order two bytes */
9295         shCount -= 16;
9296         /* if some more remaining */
9297         if (shCount)
9298             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9299         else {
9300             movLeft2Result(left, MSB16, result, MSB32);
9301             movLeft2Result(left, LSB, result, MSB24);
9302         }
9303                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9304                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9305         return;
9306     }    
9307
9308     /* if more than 1 byte */
9309     else if ( shCount >= 8 ) {
9310         /* lower order three bytes goes to higher order  three bytes */
9311         shCount -= 8;
9312         if(size == 2){
9313             if(shCount)
9314                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9315             else
9316                 movLeft2Result(left, LSB, result, MSB16);
9317         }
9318         else{   /* size = 4 */
9319             if(shCount == 0){
9320                 movLeft2Result(left, MSB24, result, MSB32);
9321                 movLeft2Result(left, MSB16, result, MSB24);
9322                 movLeft2Result(left, LSB, result, MSB16);
9323                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9324             }
9325             else if(shCount == 1)
9326                 shiftLLong(left, result, MSB16);
9327             else{
9328                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9329                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9330                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9331                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9332             }
9333         }
9334     }
9335
9336     /* 1 <= shCount <= 7 */
9337     else if(shCount <= 3)
9338     { 
9339         shiftLLong(left, result, LSB);
9340         while(--shCount >= 1)
9341             shiftLLong(result, result, LSB);
9342     }
9343     /* 3 <= shCount <= 7, optimize */
9344     else{
9345         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9346         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9347         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9348     }
9349 }
9350
9351 /*-----------------------------------------------------------------*/
9352 /* genLeftShiftLiteral - left shifting by known count              */
9353 /*-----------------------------------------------------------------*/
9354 void pic16_genLeftShiftLiteral (operand *left,
9355                                  operand *right,
9356                                  operand *result,
9357                                  iCode *ic)
9358 {    
9359     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9360     int size;
9361
9362     FENTRY;
9363     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9364     pic16_freeAsmop(right,NULL,ic,TRUE);
9365
9366     pic16_aopOp(left,ic,FALSE);
9367     pic16_aopOp(result,ic,TRUE);
9368
9369     size = getSize(operandType(result));
9370
9371 #if VIEW_SIZE
9372     pic16_emitcode("; shift left ","result %d, left %d",size,
9373              AOP_SIZE(left));
9374 #endif
9375
9376     /* I suppose that the left size >= result size */
9377     if(shCount == 0){
9378         while(size--){
9379             movLeft2Result(left, size, result, size);
9380         }
9381     }
9382
9383     else if(shCount >= (size * 8))
9384         while(size--)
9385             pic16_aopPut(AOP(result),zero,size);
9386     else{
9387         switch (size) {
9388             case 1:
9389                 genlshOne (result,left,shCount);
9390                 break;
9391
9392             case 2:
9393             case 3:
9394                 genlshTwo (result,left,shCount);
9395                 break;
9396
9397             case 4:
9398                 genlshFour (result,left,shCount);
9399                 break;
9400         }
9401     }
9402     pic16_freeAsmop(left,NULL,ic,TRUE);
9403     pic16_freeAsmop(result,NULL,ic,TRUE);
9404 }
9405
9406 /*-----------------------------------------------------------------*
9407  * genMultiAsm - repeat assembly instruction for size of register.
9408  * if endian == 1, then the high byte (i.e base address + size of 
9409  * register) is used first else the low byte is used first;
9410  *-----------------------------------------------------------------*/
9411 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9412 {
9413
9414   int offset = 0;
9415
9416   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9417
9418   if(!reg)
9419     return;
9420
9421   if(!endian) {
9422     endian = 1;
9423   } else {
9424     endian = -1;
9425     offset = size-1;
9426   }
9427
9428   while(size--) {
9429     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9430     offset += endian;
9431   }
9432
9433 }
9434
9435 #if !(USE_GENERIC_SIGNED_SHIFT)
9436 /*-----------------------------------------------------------------*/
9437 /* genLeftShift - generates code for left shifting                 */
9438 /*-----------------------------------------------------------------*/
9439 static void genLeftShift (iCode *ic)
9440 {
9441   operand *left,*right, *result;
9442   int size, offset;
9443 //  char *l;
9444   symbol *tlbl , *tlbl1;
9445   pCodeOp *pctemp;
9446
9447   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9448
9449   right = IC_RIGHT(ic);
9450   left  = IC_LEFT(ic);
9451   result = IC_RESULT(ic);
9452
9453   pic16_aopOp(right,ic,FALSE);
9454
9455   /* if the shift count is known then do it 
9456      as efficiently as possible */
9457   if (AOP_TYPE(right) == AOP_LIT) {
9458     pic16_genLeftShiftLiteral (left,right,result,ic);
9459     return ;
9460   }
9461
9462   /* shift count is unknown then we have to form
9463    * a loop. Get the loop count in WREG : Note: we take
9464    * only the lower order byte since shifting
9465    * more than 32 bits make no sense anyway, ( the
9466    * largest size of an object can be only 32 bits ) */
9467   
9468   pic16_aopOp(left,ic,FALSE);
9469   pic16_aopOp(result,ic,FALSE);
9470
9471   /* now move the left to the result if they are not the
9472    * same, and if size > 1,
9473    * and if right is not same to result (!!!) -- VR */
9474   if (!pic16_sameRegs(AOP(left),AOP(result))
9475       && (AOP_SIZE(result) > 1)) {
9476
9477     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9478
9479     size = AOP_SIZE(result);
9480     offset=0;
9481     while (size--) {
9482
9483 #if 0
9484       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9485       if (*l == '@' && (IS_AOP_PREG(result))) {
9486
9487           pic16_emitcode("mov","a,%s",l);
9488           pic16_aopPut(AOP(result),"a",offset);
9489       } else
9490 #endif
9491       {
9492         /* we don't know if left is a literal or a register, take care -- VR */
9493         pic16_mov2f(AOP(result), AOP(left), offset);
9494       }
9495       offset++;
9496     }
9497   }
9498
9499   size = AOP_SIZE(result);
9500
9501   /* if it is only one byte then */
9502   if (size == 1) {
9503     if(optimized_for_speed) {
9504       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9505       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9506       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9507       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9508       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9509       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9510       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9511       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9512       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9513       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9514       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9515       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9516     } else {
9517
9518       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9519
9520       tlbl = newiTempLabel(NULL);
9521
9522 #if 1
9523       /* this is already done, why change it? */
9524       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9525                 pic16_mov2f(AOP(result), AOP(left), 0);
9526       }
9527 #endif
9528
9529       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9530       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9531       pic16_emitpLabel(tlbl->key);
9532       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9533       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9534       emitSKPC;
9535       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9536     }
9537     goto release ;
9538   }
9539     
9540   if (pic16_sameRegs(AOP(left),AOP(result))) {
9541
9542     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9543     
9544     tlbl = newiTempLabel(NULL);
9545     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9546     genMultiAsm(POC_RRCF, result, size,1);
9547     pic16_emitpLabel(tlbl->key);
9548     genMultiAsm(POC_RLCF, result, size,0);
9549     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9550     emitSKPC;
9551     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9552     goto release;
9553   }
9554
9555   //tlbl = newiTempLabel(NULL);
9556   //offset = 0 ;   
9557   //tlbl1 = newiTempLabel(NULL);
9558
9559   //reAdjustPreg(AOP(result));    
9560     
9561   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9562   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9563   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9564   //MOVA(l);
9565   //pic16_emitcode("add","a,acc");         
9566   //pic16_aopPut(AOP(result),"a",offset++);
9567   //while (--size) {
9568   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9569   //  MOVA(l);
9570   //  pic16_emitcode("rlc","a");         
9571   //  pic16_aopPut(AOP(result),"a",offset++);
9572   //}
9573   //reAdjustPreg(AOP(result));
9574
9575   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9576   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9577
9578
9579   tlbl = newiTempLabel(NULL);
9580   tlbl1= newiTempLabel(NULL);
9581
9582   size = AOP_SIZE(result);
9583   offset = 1;
9584
9585   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9586
9587   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9588
9589   /* offset should be 0, 1 or 3 */
9590   
9591   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9592   emitSKPNZ;
9593   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9594
9595   pic16_emitpcode(POC_MOVWF, pctemp);
9596
9597
9598   pic16_emitpLabel(tlbl->key);
9599
9600   emitCLRC;
9601   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9602   while(--size)
9603     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9604
9605   pic16_emitpcode(POC_DECFSZ,  pctemp);
9606   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9607   pic16_emitpLabel(tlbl1->key);
9608
9609   pic16_popReleaseTempReg(pctemp,1);
9610
9611
9612  release:
9613   pic16_freeAsmop (right,NULL,ic,TRUE);
9614   pic16_freeAsmop(left,NULL,ic,TRUE);
9615   pic16_freeAsmop(result,NULL,ic,TRUE);
9616 }
9617 #endif
9618
9619
9620 #if 0
9621 #error old code (left here for reference)
9622 /*-----------------------------------------------------------------*/
9623 /* genLeftShift - generates code for left shifting                 */
9624 /*-----------------------------------------------------------------*/
9625 static void genLeftShift (iCode *ic)
9626 {
9627   operand *left,*right, *result;
9628   int size, offset;
9629   char *l;
9630   symbol *tlbl , *tlbl1;
9631   pCodeOp *pctemp;
9632
9633   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9634
9635   right = IC_RIGHT(ic);
9636   left  = IC_LEFT(ic);
9637   result = IC_RESULT(ic);
9638
9639   pic16_aopOp(right,ic,FALSE);
9640
9641   /* if the shift count is known then do it 
9642      as efficiently as possible */
9643   if (AOP_TYPE(right) == AOP_LIT) {
9644     pic16_genLeftShiftLiteral (left,right,result,ic);
9645     return ;
9646   }
9647
9648   /* shift count is unknown then we have to form 
9649      a loop get the loop count in B : Note: we take
9650      only the lower order byte since shifting
9651      more that 32 bits make no sense anyway, ( the
9652      largest size of an object can be only 32 bits ) */  
9653
9654     
9655   pic16_aopOp(left,ic,FALSE);
9656   pic16_aopOp(result,ic,FALSE);
9657
9658   /* now move the left to the result if they are not the
9659      same */
9660   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9661       AOP_SIZE(result) > 1) {
9662
9663     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9664
9665     size = AOP_SIZE(result);
9666     offset=0;
9667     while (size--) {
9668       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9669       if (*l == '@' && (IS_AOP_PREG(result))) {
9670
9671         pic16_emitcode("mov","a,%s",l);
9672         pic16_aopPut(AOP(result),"a",offset);
9673       } else {
9674
9675         /* we don't know if left is a literal or a register, take care -- VR */
9676         pic16_mov2f(AOP(result), AOP(left), offset);
9677       }
9678       offset++;
9679     }
9680   }
9681
9682   size = AOP_SIZE(result);
9683
9684   /* if it is only one byte then */
9685   if (size == 1) {
9686     if(optimized_for_speed) {
9687       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9688       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9689       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9690       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9691       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9692       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9693       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9694       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9695       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9696       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9697       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9698       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9699     } else {
9700
9701       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9702
9703       tlbl = newiTempLabel(NULL);
9704       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9705                 pic16_mov2f(AOP(result), AOP(left), 0);
9706                 
9707 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9708 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9709       }
9710
9711       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9712       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9713       pic16_emitpLabel(tlbl->key);
9714       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9715       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9716       emitSKPC;
9717       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9718     }
9719     goto release ;
9720   }
9721     
9722   if (pic16_sameRegs(AOP(left),AOP(result))) {
9723
9724     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9725     
9726     tlbl = newiTempLabel(NULL);
9727     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9728     genMultiAsm(POC_RRCF, result, size,1);
9729     pic16_emitpLabel(tlbl->key);
9730     genMultiAsm(POC_RLCF, result, size,0);
9731     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9732     emitSKPC;
9733     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9734     goto release;
9735   }
9736
9737   //tlbl = newiTempLabel(NULL);
9738   //offset = 0 ;   
9739   //tlbl1 = newiTempLabel(NULL);
9740
9741   //reAdjustPreg(AOP(result));    
9742     
9743   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9744   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9745   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9746   //MOVA(l);
9747   //pic16_emitcode("add","a,acc");         
9748   //pic16_aopPut(AOP(result),"a",offset++);
9749   //while (--size) {
9750   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9751   //  MOVA(l);
9752   //  pic16_emitcode("rlc","a");         
9753   //  pic16_aopPut(AOP(result),"a",offset++);
9754   //}
9755   //reAdjustPreg(AOP(result));
9756
9757   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9758   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9759
9760
9761   tlbl = newiTempLabel(NULL);
9762   tlbl1= newiTempLabel(NULL);
9763
9764   size = AOP_SIZE(result);
9765   offset = 1;
9766
9767   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9768
9769   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9770
9771   /* offset should be 0, 1 or 3 */
9772   
9773   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9774   emitSKPNZ;
9775   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9776
9777   pic16_emitpcode(POC_MOVWF, pctemp);
9778
9779
9780   pic16_emitpLabel(tlbl->key);
9781
9782   emitCLRC;
9783   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9784   while(--size)
9785     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9786
9787   pic16_emitpcode(POC_DECFSZ,  pctemp);
9788   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9789   pic16_emitpLabel(tlbl1->key);
9790
9791   pic16_popReleaseTempReg(pctemp,1);
9792
9793
9794  release:
9795   pic16_freeAsmop (right,NULL,ic,TRUE);
9796   pic16_freeAsmop(left,NULL,ic,TRUE);
9797   pic16_freeAsmop(result,NULL,ic,TRUE);
9798 }
9799 #endif
9800
9801 /*-----------------------------------------------------------------*/
9802 /* genrshOne - right shift a one byte quantity by known count      */
9803 /*-----------------------------------------------------------------*/
9804 static void genrshOne (operand *result, operand *left,
9805                        int shCount, int sign)
9806 {
9807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9808     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9809 }
9810
9811 /*-----------------------------------------------------------------*/
9812 /* genrshTwo - right shift two bytes by known amount != 0          */
9813 /*-----------------------------------------------------------------*/
9814 static void genrshTwo (operand *result,operand *left,
9815                        int shCount, int sign)
9816 {
9817   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9818   /* if shCount >= 8 */
9819   if (shCount >= 8) {
9820     shCount -= 8 ;
9821     if (shCount)
9822       shiftR1Left2Result(left, MSB16, result, LSB,
9823                          shCount, sign);
9824     else
9825       movLeft2Result(left, MSB16, result, LSB);
9826
9827     pic16_addSign (result, 1, sign);
9828   }
9829
9830   /*  1 <= shCount <= 7 */
9831   else
9832     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9833 }
9834
9835 /*-----------------------------------------------------------------*/
9836 /* shiftRLong - shift right one long from left to result           */
9837 /* offl = LSB or MSB16                                             */
9838 /*-----------------------------------------------------------------*/
9839 static void shiftRLong (operand *left, int offl,
9840                         operand *result, int sign)
9841 {
9842     int size = AOP_SIZE(result);
9843     int same = pic16_sameRegs(AOP(left),AOP(result));
9844     int i;
9845     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9846
9847         if (same && (offl == MSB16)) { //shift one byte right
9848                 for(i=MSB16;i<size;i++) {
9849                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9850                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9851                 }
9852         }
9853
9854     if(sign)
9855                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9856         else
9857                 emitCLRC;
9858
9859         if (same) {
9860                 if (offl == LSB)
9861                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9862         } else {
9863         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9864         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9865         }
9866
9867     if(offl == MSB16) {
9868         /* add sign of "a" */
9869         pic16_addSign(result, MSB32, sign);
9870         }
9871
9872         if (same) {
9873         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9874         } else {
9875         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9876         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9877         }
9878         
9879         if (same) {
9880         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9881         } else {
9882         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9883         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9884         }
9885
9886         if (same) {
9887         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9888         } else {
9889         if(offl == LSB){
9890                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9891                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9892         }
9893         }
9894 }
9895
9896 /*-----------------------------------------------------------------*/
9897 /* genrshFour - shift four byte by a known amount != 0             */
9898 /*-----------------------------------------------------------------*/
9899 static void genrshFour (operand *result, operand *left,
9900                         int shCount, int sign)
9901 {
9902   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9903   /* if shifting more that 3 bytes */
9904   if(shCount >= 24 ) {
9905     shCount -= 24;
9906     if(shCount)
9907       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9908     else
9909       movLeft2Result(left, MSB32, result, LSB);
9910
9911     pic16_addSign(result, MSB16, sign);
9912   }
9913   else if(shCount >= 16){
9914     shCount -= 16;
9915     if(shCount)
9916       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9917     else{
9918       movLeft2Result(left, MSB24, result, LSB);
9919       movLeft2Result(left, MSB32, result, MSB16);
9920     }
9921     pic16_addSign(result, MSB24, sign);
9922   }
9923   else if(shCount >= 8){
9924     shCount -= 8;
9925     if(shCount == 1)
9926       shiftRLong(left, MSB16, result, sign);
9927     else if(shCount == 0){
9928       movLeft2Result(left, MSB16, result, LSB);
9929       movLeft2Result(left, MSB24, result, MSB16);
9930       movLeft2Result(left, MSB32, result, MSB24);
9931       pic16_addSign(result, MSB32, sign);
9932     }
9933     else{ //shcount >= 2
9934       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9935       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9936       /* the last shift is signed */
9937       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9938       pic16_addSign(result, MSB32, sign);
9939     }
9940   }
9941   else{   /* 1 <= shCount <= 7 */
9942     if(shCount <= 2){
9943       shiftRLong(left, LSB, result, sign);
9944       if(shCount == 2)
9945         shiftRLong(result, LSB, result, sign);
9946     }
9947     else{
9948       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9949       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9950       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9951     }
9952   }
9953 }
9954
9955 /*-----------------------------------------------------------------*/
9956 /* genRightShiftLiteral - right shifting by known count            */
9957 /*-----------------------------------------------------------------*/
9958 static void genRightShiftLiteral (operand *left,
9959                                   operand *right,
9960                                   operand *result,
9961                                   iCode *ic,
9962                                   int sign)
9963 {    
9964   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9965   int lsize,res_size;
9966
9967   pic16_freeAsmop(right,NULL,ic,TRUE);
9968
9969   pic16_aopOp(left,ic,FALSE);
9970   pic16_aopOp(result,ic,TRUE);
9971
9972   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9973
9974 #if VIEW_SIZE
9975   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9976                  AOP_SIZE(left));
9977 #endif
9978
9979   lsize = pic16_getDataSize(left);
9980   res_size = pic16_getDataSize(result);
9981   /* test the LEFT size !!! */
9982
9983   /* I suppose that the left size >= result size */
9984   if(shCount == 0){
9985     assert (res_size <= lsize);
9986     while (res_size--) {
9987       pic16_mov2f (AOP(result), AOP(left), res_size);
9988     } // for
9989   }
9990
9991   else if(shCount >= (lsize * 8)){
9992
9993     if(res_size == 1) {
9994       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9995       if(sign) {
9996         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9997         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9998       }
9999     } else {
10000
10001       if(sign) {
10002         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10003         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10004         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10005         while(res_size--)
10006           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10007
10008       } else {
10009
10010         while(res_size--)
10011           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10012       }
10013     }
10014   } else {
10015
10016     switch (res_size) {
10017     case 1:
10018       genrshOne (result,left,shCount,sign);
10019       break;
10020
10021     case 2:
10022       genrshTwo (result,left,shCount,sign);
10023       break;
10024
10025     case 4:
10026       genrshFour (result,left,shCount,sign);
10027       break;
10028     default :
10029       break;
10030     }
10031
10032   }
10033
10034   pic16_freeAsmop(left,NULL,ic,TRUE);
10035   pic16_freeAsmop(result,NULL,ic,TRUE);
10036 }
10037
10038 #if !(USE_GENERIC_SIGNED_SHIFT)
10039 /*-----------------------------------------------------------------*/
10040 /* genSignedRightShift - right shift of signed number              */
10041 /*-----------------------------------------------------------------*/
10042 static void genSignedRightShift (iCode *ic)
10043 {
10044   operand *right, *left, *result;
10045   int size, offset;
10046   //  char *l;
10047   symbol *tlbl, *tlbl1 ;
10048   pCodeOp *pctemp;
10049
10050   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10051
10052   /* we do it the hard way put the shift count in b
10053      and loop thru preserving the sign */
10054   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10055
10056   right = IC_RIGHT(ic);
10057   left  = IC_LEFT(ic);
10058   result = IC_RESULT(ic);
10059
10060   pic16_aopOp(right,ic,FALSE);  
10061   pic16_aopOp(left,ic,FALSE);
10062   pic16_aopOp(result,ic,FALSE);
10063
10064
10065   if ( AOP_TYPE(right) == AOP_LIT) {
10066     genRightShiftLiteral (left,right,result,ic,1);
10067     return ;
10068   }
10069   /* shift count is unknown then we have to form 
10070      a loop get the loop count in B : Note: we take
10071      only the lower order byte since shifting
10072      more that 32 bits make no sense anyway, ( the
10073      largest size of an object can be only 32 bits ) */  
10074
10075   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10076   //pic16_emitcode("inc","b");
10077   //pic16_freeAsmop (right,NULL,ic,TRUE);
10078   //pic16_aopOp(left,ic,FALSE);
10079   //pic16_aopOp(result,ic,FALSE);
10080
10081   /* now move the left to the result if they are not the
10082      same */
10083   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10084       AOP_SIZE(result) > 1) {
10085
10086     size = AOP_SIZE(result);
10087     offset=0;
10088     while (size--) { 
10089       /*
10090         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10091         if (*l == '@' && IS_AOP_PREG(result)) {
10092
10093         pic16_emitcode("mov","a,%s",l);
10094         pic16_aopPut(AOP(result),"a",offset);
10095         } else
10096         pic16_aopPut(AOP(result),l,offset);
10097       */
10098       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10099       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10100
10101       offset++;
10102     }
10103   }
10104
10105   /* mov the highest order bit to OVR */    
10106   tlbl = newiTempLabel(NULL);
10107   tlbl1= newiTempLabel(NULL);
10108
10109   size = AOP_SIZE(result);
10110   offset = size - 1;
10111
10112   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10113
10114   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10115
10116   /* offset should be 0, 1 or 3 */
10117   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10118   emitSKPNZ;
10119   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10120
10121   pic16_emitpcode(POC_MOVWF, pctemp);
10122
10123
10124   pic16_emitpLabel(tlbl->key);
10125
10126   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10127   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10128
10129   while(--size) {
10130     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10131   }
10132
10133   pic16_emitpcode(POC_DECFSZ,  pctemp);
10134   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10135   pic16_emitpLabel(tlbl1->key);
10136
10137   pic16_popReleaseTempReg(pctemp,1);
10138 #if 0
10139   size = AOP_SIZE(result);
10140   offset = size - 1;
10141   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10142   pic16_emitcode("rlc","a");
10143   pic16_emitcode("mov","ov,c");
10144   /* if it is only one byte then */
10145   if (size == 1) {
10146     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10147     MOVA(l);
10148     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10149     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10150     pic16_emitcode("mov","c,ov");
10151     pic16_emitcode("rrc","a");
10152     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10153     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10154     pic16_aopPut(AOP(result),"a",0);
10155     goto release ;
10156   }
10157
10158   reAdjustPreg(AOP(result));
10159   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10160   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10161   pic16_emitcode("mov","c,ov");
10162   while (size--) {
10163     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10164     MOVA(l);
10165     pic16_emitcode("rrc","a");         
10166     pic16_aopPut(AOP(result),"a",offset--);
10167   }
10168   reAdjustPreg(AOP(result));
10169   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10170   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10171
10172  release:
10173 #endif
10174
10175   pic16_freeAsmop(left,NULL,ic,TRUE);
10176   pic16_freeAsmop(result,NULL,ic,TRUE);
10177   pic16_freeAsmop(right,NULL,ic,TRUE);
10178 }
10179 #endif
10180
10181 #if !(USE_GENERIC_SIGNED_SHIFT)
10182 #warning This implementation of genRightShift() is incomplete!
10183 /*-----------------------------------------------------------------*/
10184 /* genRightShift - generate code for right shifting                */
10185 /*-----------------------------------------------------------------*/
10186 static void genRightShift (iCode *ic)
10187 {
10188     operand *right, *left, *result;
10189     sym_link *letype ;
10190     int size, offset;
10191     char *l;
10192     symbol *tlbl, *tlbl1 ;
10193
10194     /* if signed then we do it the hard way preserve the
10195     sign bit moving it inwards */
10196     letype = getSpec(operandType(IC_LEFT(ic)));
10197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10198
10199     if (!SPEC_USIGN(letype)) {
10200         genSignedRightShift (ic);
10201         return ;
10202     }
10203
10204     /* signed & unsigned types are treated the same : i.e. the
10205     signed is NOT propagated inwards : quoting from the
10206     ANSI - standard : "for E1 >> E2, is equivalent to division
10207     by 2**E2 if unsigned or if it has a non-negative value,
10208     otherwise the result is implementation defined ", MY definition
10209     is that the sign does not get propagated */
10210
10211     right = IC_RIGHT(ic);
10212     left  = IC_LEFT(ic);
10213     result = IC_RESULT(ic);
10214
10215     pic16_aopOp(right,ic,FALSE);
10216
10217     /* if the shift count is known then do it 
10218     as efficiently as possible */
10219     if (AOP_TYPE(right) == AOP_LIT) {
10220         genRightShiftLiteral (left,right,result,ic, 0);
10221         return ;
10222     }
10223
10224     /* shift count is unknown then we have to form 
10225     a loop get the loop count in B : Note: we take
10226     only the lower order byte since shifting
10227     more that 32 bits make no sense anyway, ( the
10228     largest size of an object can be only 32 bits ) */  
10229
10230     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10231     pic16_emitcode("inc","b");
10232     pic16_aopOp(left,ic,FALSE);
10233     pic16_aopOp(result,ic,FALSE);
10234
10235     /* now move the left to the result if they are not the
10236     same */
10237     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10238         AOP_SIZE(result) > 1) {
10239
10240         size = AOP_SIZE(result);
10241         offset=0;
10242         while (size--) {
10243             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10244             if (*l == '@' && IS_AOP_PREG(result)) {
10245
10246                 pic16_emitcode("mov","a,%s",l);
10247                 pic16_aopPut(AOP(result),"a",offset);
10248             } else
10249                 pic16_aopPut(AOP(result),l,offset);
10250             offset++;
10251         }
10252     }
10253
10254     tlbl = newiTempLabel(NULL);
10255     tlbl1= newiTempLabel(NULL);
10256     size = AOP_SIZE(result);
10257     offset = size - 1;
10258
10259     /* if it is only one byte then */
10260     if (size == 1) {
10261
10262       tlbl = newiTempLabel(NULL);
10263       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10264         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10265         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10266       }
10267
10268       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10269       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10270       pic16_emitpLabel(tlbl->key);
10271       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10272       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10273       emitSKPC;
10274       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10275
10276       goto release ;
10277     }
10278
10279     reAdjustPreg(AOP(result));
10280     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10281     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10282     CLRC;
10283     while (size--) {
10284         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10285         MOVA(l);
10286         pic16_emitcode("rrc","a");         
10287         pic16_aopPut(AOP(result),"a",offset--);
10288     }
10289     reAdjustPreg(AOP(result));
10290
10291     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10292     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10293
10294 release:
10295     pic16_freeAsmop(left,NULL,ic,TRUE);
10296     pic16_freeAsmop (right,NULL,ic,TRUE);
10297     pic16_freeAsmop(result,NULL,ic,TRUE);
10298 }
10299 #endif
10300
10301 #if (USE_GENERIC_SIGNED_SHIFT)
10302 /*-----------------------------------------------------------------*/
10303 /* genGenericShift - generates code for left or right shifting     */
10304 /*-----------------------------------------------------------------*/
10305 static void genGenericShift (iCode *ic, int isShiftLeft) {
10306   operand *left,*right, *result;
10307   int offset;
10308   int sign, signedCount;
10309   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10310   PIC_OPCODE pos_shift, neg_shift;
10311
10312   FENTRY;
10313
10314   right = IC_RIGHT(ic);
10315   left  = IC_LEFT(ic);
10316   result = IC_RESULT(ic);
10317
10318   pic16_aopOp(right,ic,FALSE);
10319   pic16_aopOp(left,ic,FALSE);
10320   pic16_aopOp(result,ic,TRUE);
10321
10322   sign = !SPEC_USIGN(operandType (left));
10323   signedCount = !SPEC_USIGN(operandType (right));
10324
10325   /* if the shift count is known then do it 
10326      as efficiently as possible */
10327   if (AOP_TYPE(right) == AOP_LIT) {
10328     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10329     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10330     // we should modify right->aopu.aop_lit here!
10331     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10332     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10333     if (isShiftLeft)
10334       pic16_genLeftShiftLiteral (left,right,result,ic);
10335     else
10336       genRightShiftLiteral (left,right,result,ic, sign);
10337
10338     goto release;
10339   } // if (right is literal)
10340
10341   /* shift count is unknown then we have to form a loop.
10342    * Note: we take only the lower order byte since shifting
10343    * more than 32 bits make no sense anyway, ( the
10344    * largest size of an object can be only 32 bits )
10345    * Note: we perform arithmetic shifts if the left operand is
10346    * signed and we do an (effective) right shift, i. e. we
10347    * shift in the sign bit from the left. */
10348    
10349   label_complete = newiTempLabel ( NULL );
10350   label_loop_pos = newiTempLabel ( NULL );
10351   label_loop_neg = NULL;
10352   label_negative = NULL;
10353   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10354   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10355
10356   if (signedCount) {
10357     // additional labels needed
10358     label_loop_neg = newiTempLabel ( NULL );
10359     label_negative = newiTempLabel ( NULL );
10360   } // if
10361
10362   // copy source to result -- this will effectively truncate the left operand to the size of result!
10363   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10364   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10365   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10366     pic16_mov2f (AOP(result),AOP(left), offset);
10367   } // for
10368
10369   // if result is longer than left, fill with zeros (or sign)
10370   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10371     if (sign && AOP_SIZE(left) > 0) {
10372       // shift signed operand -- fill with sign
10373       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10374       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10375       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10376       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10377         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10378       } // for
10379     } else {
10380       // shift unsigned operand -- fill result with zeros
10381       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10382         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10383       } // for
10384     }
10385   } // if (size mismatch)
10386
10387   pic16_mov2w (AOP(right), 0);
10388   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10389   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10390   
10391 #if 0
10392   // perform a shift by one (shift count is positive)
10393   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10394   // 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])
10395   pic16_emitpLabel (label_loop_pos->key);
10396   emitCLRC;
10397   if (sign && (pos_shift == POC_RRCF)) {
10398     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10399     emitSETC;
10400   } // if
10401   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10402   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10403   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10404 #else
10405   // perform a shift by one (shift count is positive)
10406   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10407   // 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])
10408   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10409   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10410   emitCLRC;
10411   pic16_emitpLabel (label_loop_pos->key);
10412   if (sign && (pos_shift == POC_RRCF)) {
10413     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10414     emitSETC;
10415   } // if
10416   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10417   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10418   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10419   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10420 #endif
10421
10422   if (signedCount) {
10423     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10424
10425     pic16_emitpLabel (label_negative->key);
10426     // perform a shift by -1 (shift count is negative)
10427     // 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)
10428     emitCLRC;
10429     pic16_emitpLabel (label_loop_neg->key);
10430     if (sign && (neg_shift == POC_RRCF)) {
10431       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10432       emitSETC;
10433     } // if
10434     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10435     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10436     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10437     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10438   } // if (signedCount)
10439
10440   pic16_emitpLabel (label_complete->key);
10441
10442 release:
10443   pic16_freeAsmop (right,NULL,ic,TRUE);
10444   pic16_freeAsmop(left,NULL,ic,TRUE);
10445   pic16_freeAsmop(result,NULL,ic,TRUE);
10446 }
10447
10448 static void genLeftShift (iCode *ic) {
10449   genGenericShift (ic, 1);
10450 }
10451
10452 static void genRightShift (iCode *ic) {
10453   genGenericShift (ic, 0);
10454 }
10455 #endif
10456
10457
10458 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10459 void pic16_loadFSR0(operand *op, int lit)
10460 {
10461   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10462     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10463   } else {
10464     assert (!OP_SYMBOL(op)->remat);
10465     // set up FSR0 with address of result
10466     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10467     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10468   }
10469 }
10470
10471 /*----------------------------------------------------------------*/
10472 /* pic16_derefPtr - move one byte from the location ptr points to */
10473 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10474 /*                  to the location ptr points to (doWrite != 0)   */
10475 /*----------------------------------------------------------------*/
10476 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10477 {
10478   if (!IS_PTR(operandType(ptr)))
10479   {
10480     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10481     else pic16_mov2w (AOP(ptr), 0);
10482     return;
10483   }
10484
10485   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10486   /* We might determine pointer type right here: */
10487   p_type = DCL_TYPE(operandType(ptr));
10488
10489   switch (p_type) {
10490     case FPOINTER:
10491     case POINTER:
10492       if (!fsr0_setup || !*fsr0_setup)
10493       {
10494         pic16_loadFSR0( ptr, 0 );
10495         if (fsr0_setup) *fsr0_setup = 1;
10496       }
10497       if (doWrite)
10498         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10499       else
10500         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10501       break;
10502
10503     case GPOINTER:
10504       if (AOP(ptr)->aopu.aop_reg[2]) {
10505         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10506         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10507         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10508         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10509         pic16_mov2w(AOP(ptr), 2);
10510         pic16_callGenericPointerRW(doWrite, 1);
10511       } else {
10512         // data pointer (just 2 byte given)
10513         if (!fsr0_setup || !*fsr0_setup)
10514         {
10515           pic16_loadFSR0( ptr, 0 );
10516           if (fsr0_setup) *fsr0_setup = 1;
10517         }
10518         if (doWrite)
10519           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10520         else
10521           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10522       }
10523       break;
10524
10525     default:
10526       assert (0 && "invalid pointer type specified");
10527       break;
10528   }
10529 }
10530
10531 /*-----------------------------------------------------------------*/
10532 /* genUnpackBits - generates code for unpacking bits               */
10533 /*-----------------------------------------------------------------*/
10534 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10535 {    
10536   int shCnt ;
10537   sym_link *etype, *letype;
10538   int blen=0, bstr=0;
10539   int lbstr;
10540   int same;
10541   pCodeOp *op;
10542
10543   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10544   etype = getSpec(operandType(result));
10545   letype = getSpec(operandType(left));
10546
10547   //    if(IS_BITFIELD(etype)) {
10548   blen = SPEC_BLEN(etype);
10549   bstr = SPEC_BSTR(etype);
10550   //    }
10551
10552   lbstr = SPEC_BSTR( letype );
10553
10554   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10555       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10556
10557 #if 1
10558   if((blen == 1) && (bstr < 8)
10559       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10560     /* it is a single bit, so use the appropriate bit instructions */
10561     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10562
10563     same = pic16_sameRegs(AOP(left),AOP(result));
10564     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10565     pic16_emitpcode(POC_CLRF, op);
10566
10567     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10568       /* workaround to reduce the extra lfsr instruction */
10569       pic16_emitpcode(POC_BTFSC,
10570           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10571     } else {
10572       assert (PIC_IS_DATA_PTR (operandType(left)));
10573       pic16_loadFSR0 (left, 0);
10574       pic16_emitpcode(POC_BTFSC,
10575           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10576     }
10577
10578     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10579       /* unsigned bitfields result in either 0 or 1 */
10580       pic16_emitpcode(POC_INCF, op);
10581     } else {
10582       /* signed bitfields result in either 0 or -1 */
10583       pic16_emitpcode(POC_DECF, op);
10584     }
10585     if (same) {
10586       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10587     }
10588
10589     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10590     return;
10591   }
10592
10593 #endif
10594
10595   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10596     // access symbol directly
10597     pic16_mov2w (AOP(left), 0);
10598   } else {
10599     pic16_derefPtr (left, ptype, 0, NULL);
10600   }
10601
10602   /* if we have bitdisplacement then it fits   */
10603   /* into this byte completely or if length is */
10604   /* less than a byte                          */
10605   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10606
10607     /* shift right acc */
10608     AccRsh(shCnt, 0);
10609
10610     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10611           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10612
10613     /* VR -- normally I would use the following, but since we use the hack,
10614      * to avoid the masking from AccRsh, why not mask it right now? */
10615
10616     /*
10617        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10618      */
10619
10620     /* extend signed bitfields to 8 bits */
10621     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10622     {
10623       assert (blen + bstr > 0);
10624       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10625       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10626     }
10627
10628     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10629
10630     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10631     return ;
10632   }
10633
10634   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10635   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10636   exit(-1);
10637
10638   return ;
10639 }
10640
10641
10642 static void genDataPointerGet(operand *left,
10643                               operand *result,
10644                               iCode *ic)
10645 {
10646   int size, offset = 0, leoffset=0 ;
10647
10648         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10649         pic16_aopOp(result, ic, TRUE);
10650
10651         FENTRY;
10652
10653         size = AOP_SIZE(result);
10654 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10655
10656
10657 #if 0
10658         /* The following tests may save a redudant movff instruction when
10659          * accessing unions */
10660          
10661         /* if they are the same */
10662         if (operandsEqu (left, result)) {
10663                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10664                 goto release;
10665         }
10666 #endif
10667
10668 #if 0
10669         /* if they are the same registers */
10670         if (pic16_sameRegs(AOP(left),AOP(result))) {
10671                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10672                 goto release;
10673         }
10674 #endif
10675
10676 #if 1
10677         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10678                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10679                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10680                 goto release;
10681         }
10682 #endif
10683
10684
10685 #if 0
10686         if ( AOP_TYPE(left) == AOP_PCODE) {
10687                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10688                                 AOP(left)->aopu.pcop->name,
10689                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10690                                 PCOR(AOP(left)->aopu.pcop)->instance:
10691                                 PCOI(AOP(left)->aopu.pcop)->offset);
10692         }
10693 #endif
10694
10695         if(AOP(left)->aopu.pcop->type == PO_DIR)
10696                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10697
10698         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10699
10700         while (size--) {
10701                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10702                 
10703 //              pic16_DumpOp("(result)",result);
10704                 if(is_LitAOp(AOP(result))) {
10705                         pic16_mov2w(AOP(left), offset); // patch 8
10706                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10707                 } else {
10708                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10709                                 pic16_popGet(AOP(left), offset), //patch 8
10710                                 pic16_popGet(AOP(result), offset)));
10711                 }
10712
10713                 offset++;
10714                 leoffset++;
10715         }
10716
10717 release:
10718     pic16_freeAsmop(result,NULL,ic,TRUE);
10719 }
10720
10721
10722
10723 /*-----------------------------------------------------------------*/
10724 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10725 /*-----------------------------------------------------------------*/
10726 static void genNearPointerGet (operand *left, 
10727                                operand *result, 
10728                                iCode *ic)
10729 {
10730 //  asmop *aop = NULL;
10731   //regs *preg = NULL ;
10732   sym_link *rtype, *retype;
10733   sym_link *ltype, *letype;
10734
10735     FENTRY;
10736     
10737     rtype = operandType(result);
10738     retype= getSpec(rtype);
10739     ltype = operandType(left);
10740     letype= getSpec(ltype);
10741     
10742     pic16_aopOp(left,ic,FALSE);
10743
10744 //    pic16_DumpOp("(left)",left);
10745 //    pic16_DumpOp("(result)",result);
10746
10747     /* if left is rematerialisable and
10748      * result is not bit variable type and
10749      * the left is pointer to data space i.e
10750      * lower 128 bytes of space */
10751     
10752     if (AOP_TYPE(left) == AOP_PCODE
10753       && !IS_BITFIELD(retype)
10754       && DCL_TYPE(ltype) == POINTER) {
10755
10756         genDataPointerGet (left,result,ic);
10757         pic16_freeAsmop(left, NULL, ic, TRUE);
10758         return ;
10759     }
10760     
10761     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10762     pic16_aopOp (result,ic,TRUE);
10763     
10764     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10765
10766 #if 1
10767     if(IS_BITFIELD( retype )
10768       && (SPEC_BLEN(operandType(result))==1)
10769     ) {
10770       iCode *nextic;
10771       pCodeOp *jop;
10772       int bitstrt, bytestrt;
10773
10774         /* if this is bitfield of size 1, see if we are checking the value
10775          * of a single bit in an if-statement,
10776          * if yes, then don't generate usual code, but execute the
10777          * genIfx directly -- VR */
10778
10779         nextic = ic->next;
10780
10781         /* CHECK: if next iCode is IFX
10782          * and current result operand is nextic's conditional operand
10783          * and current result operand live ranges ends at nextic's key number
10784          */
10785         if((nextic->op == IFX)
10786           && (result == IC_COND(nextic))
10787           && (OP_LIVETO(result) == nextic->seq)
10788           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10789           ) {
10790             /* everything is ok then */
10791             /* find a way to optimize the genIfx iCode */
10792
10793             bytestrt = SPEC_BSTR(operandType(result))/8;
10794             bitstrt = SPEC_BSTR(operandType(result))%8;
10795             
10796             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10797
10798             genIfxpCOpJump(nextic, jop);
10799             
10800             pic16_freeAsmop(left, NULL, ic, TRUE);
10801             pic16_freeAsmop(result, NULL, ic, TRUE);
10802             return;
10803         }
10804     }
10805 #endif
10806
10807     /* if bitfield then unpack the bits */
10808     if (IS_BITFIELD(letype)) 
10809       genUnpackBits (result, left, NULL, POINTER);
10810     else {
10811       /* we have can just get the values */
10812       int size = AOP_SIZE(result);
10813       int offset = 0;   
10814         
10815       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10816
10817       pic16_loadFSR0( left, 0 );
10818
10819       while(size--) {
10820         if(size) {
10821           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10822                 pic16_popGet(AOP(result), offset++)));
10823         } else {
10824           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10825                 pic16_popGet(AOP(result), offset++)));
10826         }
10827       }
10828     }
10829
10830 #if 0
10831     /* now some housekeeping stuff */
10832     if (aop) {
10833       /* we had to allocate for this iCode */
10834       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10835       pic16_freeAsmop(NULL,aop,ic,TRUE);
10836     } else { 
10837       /* we did not allocate which means left
10838        * already in a pointer register, then
10839        * if size > 0 && this could be used again
10840        * we have to point it back to where it 
10841        * belongs */
10842       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10843       if (AOP_SIZE(result) > 1
10844         && !OP_SYMBOL(left)->remat
10845         && ( OP_SYMBOL(left)->liveTo > ic->seq
10846             || ic->depth )) {
10847 //        int size = AOP_SIZE(result) - 1;
10848 //        while (size--)
10849 //          pic16_emitcode("dec","%s",rname);
10850         }
10851     }
10852 #endif
10853
10854     /* done */
10855     pic16_freeAsmop(left,NULL,ic,TRUE);
10856     pic16_freeAsmop(result,NULL,ic,TRUE);
10857 }
10858
10859 /*-----------------------------------------------------------------*/
10860 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10861 /*-----------------------------------------------------------------*/
10862 static void genPagedPointerGet (operand *left, 
10863                                operand *result, 
10864                                iCode *ic)
10865 {
10866     asmop *aop = NULL;
10867     regs *preg = NULL ;
10868     char *rname ;
10869     sym_link *rtype, *retype;    
10870
10871     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10872
10873     rtype = operandType(result);
10874     retype= getSpec(rtype);
10875     
10876     pic16_aopOp(left,ic,FALSE);
10877
10878   /* if the value is already in a pointer register
10879        then don't need anything more */
10880     if (!AOP_INPREG(AOP(left))) {
10881         /* otherwise get a free pointer register */
10882         aop = newAsmop(0);
10883         preg = getFreePtr(ic,&aop,FALSE);
10884         pic16_emitcode("mov","%s,%s",
10885                 preg->name,
10886                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10887         rname = preg->name ;
10888     } else
10889         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10890     
10891     pic16_freeAsmop(left,NULL,ic,TRUE);
10892     pic16_aopOp (result,ic,TRUE);
10893
10894     /* if bitfield then unpack the bits */
10895     if (IS_BITFIELD(retype)) 
10896         genUnpackBits (result,left,rname,PPOINTER);
10897     else {
10898         /* we have can just get the values */
10899         int size = AOP_SIZE(result);
10900         int offset = 0 ;        
10901         
10902         while (size--) {
10903             
10904             pic16_emitcode("movx","a,@%s",rname);
10905             pic16_aopPut(AOP(result),"a",offset);
10906             
10907             offset++ ;
10908             
10909             if (size)
10910                 pic16_emitcode("inc","%s",rname);
10911         }
10912     }
10913
10914     /* now some housekeeping stuff */
10915     if (aop) {
10916         /* we had to allocate for this iCode */
10917         pic16_freeAsmop(NULL,aop,ic,TRUE);
10918     } else { 
10919         /* we did not allocate which means left
10920            already in a pointer register, then
10921            if size > 0 && this could be used again
10922            we have to point it back to where it 
10923            belongs */
10924         if (AOP_SIZE(result) > 1 &&
10925             !OP_SYMBOL(left)->remat &&
10926             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10927               ic->depth )) {
10928             int size = AOP_SIZE(result) - 1;
10929             while (size--)
10930                 pic16_emitcode("dec","%s",rname);
10931         }
10932     }
10933
10934     /* done */
10935     pic16_freeAsmop(result,NULL,ic,TRUE);
10936     
10937         
10938 }
10939
10940 #if 0
10941 /* This code is not adjusted to PIC16 and fails utterly.
10942  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10943
10944 /*-----------------------------------------------------------------*/
10945 /* genFarPointerGet - gget value from far space                    */
10946 /*-----------------------------------------------------------------*/
10947 static void genFarPointerGet (operand *left,
10948                               operand *result, iCode *ic)
10949 {
10950     int size, offset ;
10951     sym_link *retype = getSpec(operandType(result));
10952
10953     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10954
10955     pic16_aopOp(left,ic,FALSE);
10956
10957     /* if the operand is already in dptr 
10958     then we do nothing else we move the value to dptr */
10959     if (AOP_TYPE(left) != AOP_STR) {
10960         /* if this is remateriazable */
10961         if (AOP_TYPE(left) == AOP_IMMD)
10962             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10963         else { /* we need to get it byte by byte */
10964             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10965             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10966             if (options.model == MODEL_FLAT24)
10967             {
10968                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10969             }
10970         }
10971     }
10972     /* so dptr know contains the address */
10973     pic16_freeAsmop(left,NULL,ic,TRUE);
10974     pic16_aopOp(result,ic,TRUE);
10975
10976     /* if bit then unpack */
10977     if (IS_BITFIELD(retype)) 
10978         genUnpackBits(result,left,"dptr",FPOINTER);
10979     else {
10980         size = AOP_SIZE(result);
10981         offset = 0 ;
10982
10983         while (size--) {
10984             pic16_emitcode("movx","a,@dptr");
10985             pic16_aopPut(AOP(result),"a",offset++);
10986             if (size)
10987                 pic16_emitcode("inc","dptr");
10988         }
10989     }
10990
10991     pic16_freeAsmop(result,NULL,ic,TRUE);
10992 }
10993 #endif
10994
10995 #if 0
10996 /*-----------------------------------------------------------------*/
10997 /* genCodePointerGet - get value from code space                  */
10998 /*-----------------------------------------------------------------*/
10999 static void genCodePointerGet (operand *left,
11000                                 operand *result, iCode *ic)
11001 {
11002     int size, offset ;
11003     sym_link *retype = getSpec(operandType(result));
11004
11005     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11006
11007     pic16_aopOp(left,ic,FALSE);
11008
11009     /* if the operand is already in dptr 
11010     then we do nothing else we move the value to dptr */
11011     if (AOP_TYPE(left) != AOP_STR) {
11012         /* if this is remateriazable */
11013         if (AOP_TYPE(left) == AOP_IMMD)
11014             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11015         else { /* we need to get it byte by byte */
11016             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11017             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11018             if (options.model == MODEL_FLAT24)
11019             {
11020                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11021             }
11022         }
11023     }
11024     /* so dptr know contains the address */
11025     pic16_freeAsmop(left,NULL,ic,TRUE);
11026     pic16_aopOp(result,ic,FALSE);
11027
11028     /* if bit then unpack */
11029     if (IS_BITFIELD(retype)) 
11030         genUnpackBits(result,left,"dptr",CPOINTER);
11031     else {
11032         size = AOP_SIZE(result);
11033         offset = 0 ;
11034
11035         while (size--) {
11036             pic16_emitcode("clr","a");
11037             pic16_emitcode("movc","a,@a+dptr");
11038             pic16_aopPut(AOP(result),"a",offset++);
11039             if (size)
11040                 pic16_emitcode("inc","dptr");
11041         }
11042     }
11043
11044     pic16_freeAsmop(result,NULL,ic,TRUE);
11045 }
11046 #endif
11047
11048 #if 0
11049 /*-----------------------------------------------------------------*/
11050 /* genGenPointerGet - gget value from generic pointer space        */
11051 /*-----------------------------------------------------------------*/
11052 static void genGenPointerGet (operand *left,
11053                               operand *result, iCode *ic)
11054 {
11055   int size, offset, lit;
11056   sym_link *retype = getSpec(operandType(result));
11057
11058         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11059         pic16_aopOp(left,ic,FALSE);
11060         pic16_aopOp(result,ic,FALSE);
11061         size = AOP_SIZE(result);
11062
11063         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11064
11065         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11066
11067                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11068                 // load FSR0 from immediate
11069                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11070
11071 //              pic16_loadFSR0( left );
11072
11073                 offset = 0;
11074                 while(size--) {
11075                         if(size) {
11076                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11077                         } else {
11078                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11079                         }
11080                         offset++;
11081                 }
11082                 goto release;
11083
11084         }
11085         else { /* we need to get it byte by byte */
11086                 // set up FSR0 with address from left
11087                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11088                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11089                 
11090                 offset = 0 ;
11091
11092                 while(size--) {
11093                         if(size) {
11094                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11095                         } else {
11096                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11097                         }
11098                         offset++;
11099                 }
11100                 goto release;
11101         }
11102
11103   /* if bit then unpack */
11104         if (IS_BITFIELD(retype)) 
11105                 genUnpackBits(result,left,"BAD",GPOINTER);
11106
11107         release:
11108         pic16_freeAsmop(left,NULL,ic,TRUE);
11109         pic16_freeAsmop(result,NULL,ic,TRUE);
11110
11111 }
11112 #endif
11113
11114
11115 /*-----------------------------------------------------------------*/
11116 /* genGenPointerGet - gget value from generic pointer space        */
11117 /*-----------------------------------------------------------------*/
11118 static void genGenPointerGet (operand *left,
11119                               operand *result, iCode *ic)
11120 {
11121   int size, offset, lit;
11122   sym_link *letype = getSpec(operandType(left));
11123
11124     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11125     pic16_aopOp(left,ic,FALSE);
11126     pic16_aopOp(result,ic,TRUE);
11127     size = AOP_SIZE(result);
11128
11129     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11130   
11131     /* if bit then unpack */
11132     if (IS_BITFIELD(letype)) {
11133       genUnpackBits(result,left,"BAD",GPOINTER);
11134       goto release;
11135     }
11136
11137     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11138
11139       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11140       // load FSR0 from immediate
11141       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11142
11143       werror(W_POSSBUG2, __FILE__, __LINE__);
11144
11145       offset = 0;
11146       while(size--) {
11147         if(size) {
11148           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11149         } else {
11150           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11151         }
11152         offset++;
11153       }
11154
11155       goto release;
11156
11157     } else { /* we need to get it byte by byte */
11158
11159       /* set up WREG:PRODL:FSR0L with address from left */
11160       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11161       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11162       pic16_mov2w(AOP(left), 2);
11163       pic16_callGenericPointerRW(0, size);
11164       
11165       assignResultValue(result, 1);
11166       
11167       goto release;
11168     }
11169
11170 release:
11171   pic16_freeAsmop(left,NULL,ic,TRUE);
11172   pic16_freeAsmop(result,NULL,ic,TRUE);
11173 }
11174
11175 /*-----------------------------------------------------------------*/
11176 /* genConstPointerGet - get value from const generic pointer space */
11177 /*-----------------------------------------------------------------*/
11178 static void genConstPointerGet (operand *left,
11179                                 operand *result, iCode *ic)
11180 {
11181   //sym_link *retype = getSpec(operandType(result));
11182   // symbol *albl = newiTempLabel(NULL);        // patch 15
11183   // symbol *blbl = newiTempLabel(NULL);        //
11184   // PIC_OPCODE poc;                            // patch 15
11185   int size;
11186   int offset = 0;
11187
11188   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11189   pic16_aopOp(left,ic,FALSE);
11190   pic16_aopOp(result,ic,TRUE);
11191   size = AOP_SIZE(result);
11192
11193   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11194
11195   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11196
11197   // set up table pointer
11198   if( (AOP_TYPE(left) == AOP_PCODE) 
11199       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11200           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11201     {
11202       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11203       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11204       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11205       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11206       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11207       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11208   } else {
11209     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11210     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11211     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11212   }
11213
11214   while(size--) {
11215     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11216     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11217     offset++;
11218   }
11219     
11220   pic16_freeAsmop(left,NULL,ic,TRUE);
11221   pic16_freeAsmop(result,NULL,ic,TRUE);
11222 }
11223
11224
11225 /*-----------------------------------------------------------------*/
11226 /* genPointerGet - generate code for pointer get                   */
11227 /*-----------------------------------------------------------------*/
11228 static void genPointerGet (iCode *ic)
11229 {
11230   operand *left, *result ;
11231   sym_link *type, *etype;
11232   int p_type;
11233
11234     FENTRY;
11235     
11236     left = IC_LEFT(ic);
11237     result = IC_RESULT(ic) ;
11238
11239     /* depending on the type of pointer we need to
11240     move it to the correct pointer register */
11241     type = operandType(left);
11242     etype = getSpec(type);
11243
11244 #if 0
11245     if (IS_PTR_CONST(type))
11246 #else
11247     if (IS_CODEPTR(type))
11248 #endif
11249       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11250
11251     /* if left is of type of pointer then it is simple */
11252     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11253       p_type = DCL_TYPE(type);
11254     else {
11255       /* we have to go by the storage class */
11256       p_type = PTR_TYPE(SPEC_OCLS(etype));
11257
11258       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11259
11260       if (SPEC_OCLS(etype)->codesp ) {
11261         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11262         //p_type = CPOINTER ;   
11263       } else
11264       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11265         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11266         /*p_type = FPOINTER ;*/ 
11267       } else
11268       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11269         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11270         /* p_type = PPOINTER; */
11271       } else
11272       if (SPEC_OCLS(etype) == idata ) {
11273         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11274         /* p_type = IPOINTER; */
11275       } else {
11276         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11277         /* p_type = POINTER ; */
11278       }
11279     }
11280
11281     /* now that we have the pointer type we assign
11282     the pointer values */
11283     switch (p_type) {
11284       case POINTER:     
11285       case FPOINTER:
11286       case IPOINTER:
11287         genNearPointerGet (left,result,ic);
11288         break;
11289
11290       case PPOINTER:
11291         genPagedPointerGet(left,result,ic);
11292         break;
11293
11294 #if 0
11295       /* PICs do not support FAR pointers... */
11296       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11297       case FPOINTER:
11298         genFarPointerGet (left,result,ic);
11299         break;
11300 #endif
11301
11302       case CPOINTER:
11303         genConstPointerGet (left,result,ic);
11304         //pic16_emitcodePointerGet (left,result,ic);
11305         break;
11306
11307       case GPOINTER:
11308 #if 0
11309       if (IS_PTR_CONST(type))
11310         genConstPointerGet (left,result,ic);
11311       else
11312 #endif
11313         genGenPointerGet (left,result,ic);
11314       break;
11315
11316     default:
11317       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11318               "genPointerGet: illegal pointer type");
11319     
11320     }
11321 }
11322
11323 /*-----------------------------------------------------------------*/
11324 /* genPackBits - generates code for packed bit storage             */
11325 /*-----------------------------------------------------------------*/
11326 static void genPackBits (sym_link    *etype , operand *result,
11327                          operand *right ,
11328                          char *rname, int p_type)
11329 {
11330   int shCnt = 0 ;
11331   int offset = 0  ;
11332   int rLen = 0 ;
11333   int blen, bstr ;   
11334   int shifted_and_masked = 0;
11335   unsigned long lit = (unsigned long)-1;
11336   sym_link *retype;
11337
11338   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11339   blen = SPEC_BLEN(etype);
11340   bstr = SPEC_BSTR(etype);
11341
11342   retype = getSpec(operandType(right));
11343
11344   if(AOP_TYPE(right) == AOP_LIT) {
11345     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11346     
11347     if((blen == 1) && (bstr < 8)) {
11348       /* it is a single bit, so use the appropriate bit instructions */
11349
11350       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11351
11352       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11353         /* workaround to reduce the extra lfsr instruction */
11354         if(lit) {
11355           pic16_emitpcode(POC_BSF,
11356               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11357         } else {
11358           pic16_emitpcode(POC_BCF,
11359               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11360         }
11361       } else {
11362         if (PIC_IS_DATA_PTR(operandType(result))) {
11363           pic16_loadFSR0(result, 0);
11364           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11365               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11366         } else {
11367           /* get old value */
11368           pic16_derefPtr (result, p_type, 0, NULL);
11369           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11370               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11371           /* write back new value */
11372           pic16_derefPtr (result, p_type, 1, NULL);
11373         }
11374       }
11375
11376       return;
11377     }
11378     /* IORLW below is more efficient */
11379     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11380     lit = (lit & ((1UL << blen) - 1)) << bstr;
11381     shifted_and_masked = 1;
11382     offset++;
11383   } else
11384     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11385         && IS_BITFIELD(retype) 
11386         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11387         && (blen == 1)) {
11388       int rblen, rbstr;
11389
11390       rblen = SPEC_BLEN( retype );
11391       rbstr = SPEC_BSTR( retype );
11392
11393       if(IS_BITFIELD(etype)) {
11394         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11395         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11396       } else {
11397         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11398       }
11399
11400       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11401
11402       if(IS_BITFIELD(etype)) {
11403         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11404       } else {
11405         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11406       }
11407
11408       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11409
11410       return;
11411     } else {
11412       /* move right to W */
11413       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11414     }
11415
11416   /* if the bit length is less than or   */
11417   /* it exactly fits a byte then         */
11418   if((shCnt=SPEC_BSTR(etype))
11419       || SPEC_BLEN(etype) <= 8 )  {
11420     int fsr0_setup = 0;
11421
11422     if (blen != 8 || bstr != 0) {
11423       // we need to combine the value with the old value
11424       if(!shifted_and_masked)
11425       {
11426         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11427
11428         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11429             SPEC_BSTR(etype), SPEC_BLEN(etype));
11430
11431         /* shift left acc, do NOT mask the result again */
11432         AccLsh(shCnt, 0);
11433
11434         /* using PRODH as a temporary register here */
11435         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11436       }
11437
11438       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11439         || IS_DIRECT(result)) {
11440         /* access symbol directly */
11441         pic16_mov2w (AOP(result), 0);
11442       } else {
11443         /* get old value */
11444         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11445       }
11446 #if 1
11447       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11448             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11449                             (unsigned char)(0xff >> (8-bstr))) ));
11450       if (!shifted_and_masked) {
11451         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11452       } else {
11453         /* We have the shifted and masked (literal) right value in `lit' */
11454         if (lit != 0)
11455           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11456       }
11457     } // if (blen != 8 || bstr != 0)
11458
11459     /* write new value back */
11460     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11461         || IS_DIRECT(result)) {
11462       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11463     } else {
11464       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11465     }
11466 #endif
11467
11468     return;
11469   }
11470
11471
11472 #if 0
11473   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11474   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11475   exit(-1);
11476 #endif
11477
11478
11479   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11480   rLen = SPEC_BLEN(etype)-8;
11481
11482   /* now generate for lengths greater than one byte */
11483   while (1) {
11484     rLen -= 8 ;
11485     if (rLen <= 0 ) {
11486       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11487       break ;
11488     }
11489
11490     switch (p_type) {
11491       case POINTER:
11492         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11493         break;
11494
11495         /*
11496            case FPOINTER:
11497            MOVA(l);
11498            pic16_emitcode("movx","@dptr,a");
11499            break;
11500
11501            case GPOINTER:
11502            MOVA(l);
11503            DEBUGpic16_emitcode(";lcall","__gptrput");
11504            break;  
11505          */
11506       default:
11507         assert(0);
11508     }   
11509
11510
11511     pic16_mov2w(AOP(right), offset++);
11512   }
11513
11514   /* last last was not complete */
11515   if (rLen)   {
11516     /* save the byte & read byte */
11517     switch (p_type) {
11518       case POINTER:
11519         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11520         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11521         break;
11522
11523         /*
11524            case FPOINTER:
11525            pic16_emitcode ("mov","b,a");
11526            pic16_emitcode("movx","a,@dptr");
11527            break;
11528
11529            case GPOINTER:
11530            pic16_emitcode ("push","b");
11531            pic16_emitcode ("push","acc");
11532            pic16_emitcode ("lcall","__gptrget");
11533            pic16_emitcode ("pop","b");
11534            break;
11535          */
11536       default:
11537         assert(0);
11538     }
11539     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11540     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11541     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11542     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11543     //        pic16_emitcode ("orl","a,b");
11544   }
11545
11546   //    if (p_type == GPOINTER)
11547   //        pic16_emitcode("pop","b");
11548
11549   switch (p_type) {
11550
11551     case POINTER:
11552       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11553       //        pic16_emitcode("mov","@%s,a",rname);
11554       break;
11555       /*
11556          case FPOINTER:
11557          pic16_emitcode("movx","@dptr,a");
11558          break;
11559
11560          case GPOINTER:
11561          DEBUGpic16_emitcode(";lcall","__gptrput");
11562          break;                 
11563        */
11564     default:
11565       assert(0);
11566   }
11567
11568   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11569 }
11570
11571 /*-----------------------------------------------------------------*/
11572 /* genDataPointerSet - remat pointer to data space                 */
11573 /*-----------------------------------------------------------------*/
11574 static void genDataPointerSet(operand *right,
11575                               operand *result,
11576                               iCode *ic)
11577 {
11578     int size, offset = 0, resoffset=0 ;
11579
11580     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11581     pic16_aopOp(right,ic,FALSE);
11582
11583     size = AOP_SIZE(right);
11584
11585 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11586
11587 #if 0
11588     if ( AOP_TYPE(result) == AOP_PCODE) {
11589       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11590               AOP(result)->aopu.pcop->name,
11591                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11592               PCOR(AOP(result)->aopu.pcop)->instance:
11593               PCOI(AOP(result)->aopu.pcop)->offset);
11594     }
11595 #endif
11596
11597         if(AOP(result)->aopu.pcop->type == PO_DIR)
11598                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11599
11600         while (size--) {
11601                 if (AOP_TYPE(right) == AOP_LIT) {
11602                   unsigned int lit;
11603
11604                     if(!IS_FLOAT(operandType( right )))
11605                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11606                     else {
11607                       union {
11608                         unsigned long lit_int;
11609                         float lit_float;
11610                       } info;
11611         
11612                         /* take care if literal is a float */
11613                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11614                         lit = info.lit_int;
11615                     }
11616
11617                     lit = lit >> (8*offset);
11618                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11619                 } else {
11620                   pic16_mov2w(AOP(right), offset);
11621                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11622                 }
11623                 offset++;
11624                 resoffset++;
11625         }
11626
11627     pic16_freeAsmop(right,NULL,ic,TRUE);
11628 }
11629
11630
11631
11632 /*-----------------------------------------------------------------*/
11633 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11634 /*-----------------------------------------------------------------*/
11635 static void genNearPointerSet (operand *right,
11636                                operand *result, 
11637                                iCode *ic)
11638 {
11639   asmop *aop = NULL;
11640   sym_link *retype;
11641   sym_link *ptype = operandType(result);
11642   sym_link *resetype;
11643     
11644         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11645         retype= getSpec(operandType(right));
11646         resetype = getSpec(operandType(result));
11647   
11648         pic16_aopOp(result,ic,FALSE);
11649     
11650         /* if the result is rematerializable &
11651          * in data space & not a bit variable */
11652         
11653         /* and result is not a bit variable */
11654         if (AOP_TYPE(result) == AOP_PCODE
11655 //              && AOP_TYPE(result) == AOP_IMMD
11656                 && DCL_TYPE(ptype) == POINTER
11657                 && !IS_BITFIELD(retype)
11658                 && !IS_BITFIELD(resetype)) {
11659
11660                 genDataPointerSet (right,result,ic);
11661                 pic16_freeAsmop(result,NULL,ic,TRUE);
11662           return;
11663         }
11664
11665         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11666         pic16_aopOp(right,ic,FALSE);
11667         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11668
11669         /* if bitfield then unpack the bits */
11670         if (IS_BITFIELD(resetype)) {
11671                 genPackBits (resetype, result, right, NULL, POINTER);
11672         } else {
11673                 /* we have can just get the values */
11674           int size = AOP_SIZE(right);
11675           int offset = 0 ;    
11676
11677             pic16_loadFSR0(result, 0);
11678             
11679                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11680                 while (size--) {
11681                                 if (AOP_TYPE(right) == AOP_LIT) {
11682                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11683                                         if (size) {
11684                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11685                                         } else {
11686                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11687                                         }
11688                                 } else { // no literal
11689                                         if(size) {
11690                                                 pic16_emitpcode(POC_MOVFF,
11691                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11692                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11693                                         } else {
11694                                                 pic16_emitpcode(POC_MOVFF,
11695                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11696                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11697                                         }
11698                                 }
11699                         offset++;
11700                 }
11701         }
11702
11703         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11704         /* now some housekeeping stuff */
11705         if (aop) {
11706           /* we had to allocate for this iCode */
11707           pic16_freeAsmop(NULL,aop,ic,TRUE);
11708         } else { 
11709           /* we did not allocate which means left
11710            * already in a pointer register, then
11711            * if size > 0 && this could be used again
11712            * we have to point it back to where it 
11713            * belongs */
11714           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11715           if (AOP_SIZE(right) > 1
11716             && !OP_SYMBOL(result)->remat
11717             && ( OP_SYMBOL(result)->liveTo > ic->seq
11718             || ic->depth )) {
11719
11720               int size = AOP_SIZE(right) - 1;
11721
11722                 while (size--)
11723                   pic16_emitcode("decf","fsr0,f");
11724                   //pic16_emitcode("dec","%s",rname);
11725             }
11726         }
11727
11728     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11729     /* done */
11730 //release:
11731     pic16_freeAsmop(right,NULL,ic,TRUE);
11732     pic16_freeAsmop(result,NULL,ic,TRUE);
11733 }
11734
11735 /*-----------------------------------------------------------------*/
11736 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11737 /*-----------------------------------------------------------------*/
11738 static void genPagedPointerSet (operand *right,
11739                                operand *result, 
11740                                iCode *ic)
11741 {
11742     asmop *aop = NULL;
11743     regs *preg = NULL ;
11744     char *rname , *l;
11745     sym_link *retype;
11746        
11747     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11748
11749     retype= getSpec(operandType(right));
11750     
11751     pic16_aopOp(result,ic,FALSE);
11752     
11753     /* if the value is already in a pointer register
11754        then don't need anything more */
11755     if (!AOP_INPREG(AOP(result))) {
11756         /* otherwise get a free pointer register */
11757         aop = newAsmop(0);
11758         preg = getFreePtr(ic,&aop,FALSE);
11759         pic16_emitcode("mov","%s,%s",
11760                 preg->name,
11761                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11762         rname = preg->name ;
11763     } else
11764         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11765     
11766     pic16_freeAsmop(result,NULL,ic,TRUE);
11767     pic16_aopOp (right,ic,FALSE);
11768
11769     /* if bitfield then unpack the bits */
11770     if (IS_BITFIELD(retype)) 
11771         genPackBits (retype,result,right,rname,PPOINTER);
11772     else {
11773         /* we have can just get the values */
11774         int size = AOP_SIZE(right);
11775         int offset = 0 ;        
11776         
11777         while (size--) {
11778             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11779             
11780             MOVA(l);
11781             pic16_emitcode("movx","@%s,a",rname);
11782
11783             if (size)
11784                 pic16_emitcode("inc","%s",rname);
11785
11786             offset++;
11787         }
11788     }
11789     
11790     /* now some housekeeping stuff */
11791     if (aop) {
11792         /* we had to allocate for this iCode */
11793         pic16_freeAsmop(NULL,aop,ic,TRUE);
11794     } else { 
11795         /* we did not allocate which means left
11796            already in a pointer register, then
11797            if size > 0 && this could be used again
11798            we have to point it back to where it 
11799            belongs */
11800         if (AOP_SIZE(right) > 1 &&
11801             !OP_SYMBOL(result)->remat &&
11802             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11803               ic->depth )) {
11804             int size = AOP_SIZE(right) - 1;
11805             while (size--)
11806                 pic16_emitcode("dec","%s",rname);
11807         }
11808     }
11809
11810     /* done */
11811     pic16_freeAsmop(right,NULL,ic,TRUE);
11812     
11813         
11814 }
11815
11816 #if 0
11817 /* This code is not adjusted to PIC16 and fails utterly...
11818  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11819
11820 /*-----------------------------------------------------------------*/
11821 /* genFarPointerSet - set value from far space                     */
11822 /*-----------------------------------------------------------------*/
11823 static void genFarPointerSet (operand *right,
11824                               operand *result, iCode *ic)
11825 {
11826     int size, offset ;
11827     sym_link *retype = getSpec(operandType(right));
11828
11829     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11830     pic16_aopOp(result,ic,FALSE);
11831
11832     /* if the operand is already in dptr 
11833     then we do nothing else we move the value to dptr */
11834     if (AOP_TYPE(result) != AOP_STR) {
11835         /* if this is remateriazable */
11836         if (AOP_TYPE(result) == AOP_IMMD)
11837             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11838         else { /* we need to get it byte by byte */
11839             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11840             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11841             if (options.model == MODEL_FLAT24)
11842             {
11843                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11844             }
11845         }
11846     }
11847     /* so dptr know contains the address */
11848     pic16_freeAsmop(result,NULL,ic,TRUE);
11849     pic16_aopOp(right,ic,FALSE);
11850
11851     /* if bit then unpack */
11852     if (IS_BITFIELD(retype)) 
11853         genPackBits(retype,result,right,"dptr",FPOINTER);
11854     else {
11855         size = AOP_SIZE(right);
11856         offset = 0 ;
11857
11858         while (size--) {
11859             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11860             MOVA(l);
11861             pic16_emitcode("movx","@dptr,a");
11862             if (size)
11863                 pic16_emitcode("inc","dptr");
11864         }
11865     }
11866
11867     pic16_freeAsmop(right,NULL,ic,TRUE);
11868 }
11869 #endif
11870
11871 /*-----------------------------------------------------------------*/
11872 /* genGenPointerSet - set value from generic pointer space         */
11873 /*-----------------------------------------------------------------*/
11874 #if 0
11875 static void genGenPointerSet (operand *right,
11876                               operand *result, iCode *ic)
11877 {
11878         int i, size, offset, lit;
11879         sym_link *retype = getSpec(operandType(right));
11880
11881         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11882
11883         pic16_aopOp(result,ic,FALSE);
11884         pic16_aopOp(right,ic,FALSE);
11885         size = AOP_SIZE(right);
11886         offset = 0;
11887
11888         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11889
11890         /* if the operand is already in dptr 
11891                 then we do nothing else we move the value to dptr */
11892         if (AOP_TYPE(result) != AOP_STR) {
11893                 /* if this is remateriazable */
11894                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11895                 // WARNING: anythig until "else" is untested!
11896                 if (AOP_TYPE(result) == AOP_IMMD) {
11897                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11898                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11899                         // load FSR0 from immediate
11900                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11901                         offset = 0;
11902                         while(size--) {
11903                                 if(size) {
11904                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11905                                 } else {
11906                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11907                                 }
11908                                 offset++;
11909                         }
11910                         goto release;
11911                 }
11912                 else { /* we need to get it byte by byte */
11913                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11914                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11915
11916                         // set up FSR0 with address of result
11917                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11918                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11919
11920                         /* hack hack! see if this the FSR. If so don't load W */
11921                         if(AOP_TYPE(right) != AOP_ACC) {
11922
11923                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11924
11925                                 if(AOP_TYPE(right) == AOP_LIT)
11926                                 {
11927                                         // copy literal
11928                                         // note: pic16_popGet handles sign extension
11929                                         for(i=0;i<size;i++) {
11930                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11931                                                 if(i < size-1)
11932                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11933                                                 else
11934                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11935                                         }
11936                                 } else {
11937                                         // copy regs
11938
11939                                         for(i=0;i<size;i++) {
11940                                                 if(i < size-1)
11941                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11942                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11943                                                 else
11944                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11945                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11946                                         }
11947                                 }
11948                                 goto release;
11949                         } 
11950                         // right = ACC
11951                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11952                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11953                         goto release;
11954         } // if (AOP_TYPE(result) != AOP_IMMD)
11955
11956         } // if (AOP_TYPE(result) != AOP_STR)
11957         /* so dptr know contains the address */
11958
11959
11960         /* if bit then unpack */
11961         if (IS_BITFIELD(retype)) 
11962                 genPackBits(retype,result,right,"dptr",GPOINTER);
11963         else {
11964                 size = AOP_SIZE(right);
11965                 offset = 0 ;
11966
11967                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11968
11969                 // set up FSR0 with address of result
11970                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11971                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11972         
11973                 while (size--) {
11974                         if (AOP_TYPE(right) == AOP_LIT) {
11975                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11976                                 if (size) {
11977                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11978                                 } else {
11979                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11980                                 }
11981                         } else { // no literal
11982                                 if(size) {
11983                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11984                                 } else {
11985                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11986                                 }
11987                         }
11988                         offset++;
11989                 }
11990         }
11991
11992         release:
11993         pic16_freeAsmop(right,NULL,ic,TRUE);
11994         pic16_freeAsmop(result,NULL,ic,TRUE);
11995 }
11996 #endif
11997
11998 static void genGenPointerSet (operand *right,
11999                               operand *result, iCode *ic)
12000 {
12001   int size;
12002   sym_link *retype = getSpec(operandType(result));
12003
12004     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12005
12006     pic16_aopOp(result,ic,FALSE);
12007     pic16_aopOp(right,ic,FALSE);
12008     size = AOP_SIZE(right);
12009
12010     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12011
12012
12013     /* if bit then unpack */
12014     if (IS_BITFIELD(retype)) {
12015 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12016       genPackBits(retype,result,right,"dptr",GPOINTER);
12017       goto release;
12018     }
12019
12020     size = AOP_SIZE(right);
12021
12022     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12023
12024
12025     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12026
12027     /* value of right+0 is placed on stack, which will be retrieved
12028      * by the support function this restoring the stack. The important
12029      * thing is that there is no need to manually restore stack pointer
12030      * here */
12031     pushaop(AOP(right), 0);
12032 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12033     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12034     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12035     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12036     
12037     /* load address to write to in WREG:FSR0H:FSR0L */
12038     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12039                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12040     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12041                                 pic16_popCopyReg(&pic16_pc_prodl)));
12042     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12043     
12044     pic16_callGenericPointerRW(1, size);
12045
12046 release:
12047     pic16_freeAsmop(right,NULL,ic,TRUE);
12048     pic16_freeAsmop(result,NULL,ic,TRUE);
12049 }
12050
12051 /*-----------------------------------------------------------------*/
12052 /* genPointerSet - stores the value into a pointer location        */
12053 /*-----------------------------------------------------------------*/
12054 static void genPointerSet (iCode *ic)
12055 {    
12056   operand *right, *result ;
12057   sym_link *type, *etype;
12058   int p_type;
12059
12060     FENTRY;
12061
12062     right = IC_RIGHT(ic);
12063     result = IC_RESULT(ic) ;
12064
12065     /* depending on the type of pointer we need to
12066     move it to the correct pointer register */
12067     type = operandType(result);
12068     etype = getSpec(type);
12069     
12070     /* if left is of type of pointer then it is simple */
12071     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12072         p_type = DCL_TYPE(type);
12073     }
12074     else {
12075         /* we have to go by the storage class */
12076         p_type = PTR_TYPE(SPEC_OCLS(etype));
12077
12078 /*      if (SPEC_OCLS(etype)->codesp ) { */
12079 /*          p_type = CPOINTER ;  */
12080 /*      } */
12081 /*      else */
12082 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12083 /*              p_type = FPOINTER ; */
12084 /*          else */
12085 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12086 /*                  p_type = PPOINTER ; */
12087 /*              else */
12088 /*                  if (SPEC_OCLS(etype) == idata ) */
12089 /*                      p_type = IPOINTER ; */
12090 /*                  else */
12091 /*                      p_type = POINTER ; */
12092     }
12093
12094     /* now that we have the pointer type we assign
12095     the pointer values */
12096     switch (p_type) {
12097       case POINTER:
12098       case FPOINTER:
12099       case IPOINTER:
12100         genNearPointerSet (right,result,ic);
12101         break;
12102
12103       case PPOINTER:
12104         genPagedPointerSet (right,result,ic);
12105         break;
12106
12107 #if 0
12108       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12109       case FPOINTER:
12110         genFarPointerSet (right,result,ic);
12111         break;
12112 #endif
12113         
12114       case GPOINTER:
12115         genGenPointerSet (right,result,ic);
12116         break;
12117
12118       default:
12119         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12120           "genPointerSet: illegal pointer type");
12121     }
12122 }
12123
12124 /*-----------------------------------------------------------------*/
12125 /* genIfx - generate code for Ifx statement                        */
12126 /*-----------------------------------------------------------------*/
12127 static void genIfx (iCode *ic, iCode *popIc)
12128 {
12129   operand *cond = IC_COND(ic);
12130   int isbit =0;
12131
12132     FENTRY;
12133
12134     pic16_aopOp(cond,ic,FALSE);
12135
12136     /* get the value into acc */
12137     if (AOP_TYPE(cond) != AOP_CRY)
12138       pic16_toBoolean(cond);
12139     else
12140       isbit = 1;
12141     /* the result is now in the accumulator */
12142     pic16_freeAsmop(cond,NULL,ic,TRUE);
12143
12144     /* if there was something to be popped then do it */
12145     if (popIc)
12146       genIpop(popIc);
12147
12148     /* if the condition is  a bit variable */
12149     if (isbit && IS_ITEMP(cond) && 
12150         SPIL_LOC(cond)) {
12151       genIfxJump(ic,"c");
12152       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12153     } else {
12154       if (isbit && !IS_ITEMP(cond))
12155         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12156         else
12157         genIfxJump(ic,"a");
12158     }
12159     ic->generated = 1;
12160 }
12161
12162 /*-----------------------------------------------------------------*/
12163 /* genAddrOf - generates code for address of                       */
12164 /*-----------------------------------------------------------------*/
12165 static void genAddrOf (iCode *ic)
12166 {
12167   operand *result, *left;
12168   int size;
12169   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12170   pCodeOp *pcop0, *pcop1, *pcop2;
12171
12172     FENTRY;
12173
12174     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12175
12176     sym = OP_SYMBOL( IC_LEFT(ic) );
12177     
12178     if(sym->onStack) {
12179       /* get address of symbol on stack */
12180       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12181 #if 0
12182       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12183                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12184 #endif
12185
12186       // operands on stack are accessible via "FSR2 + index" with index
12187       // starting at 2 for arguments and growing from 0 downwards for
12188       // local variables (index == 0 is not assigned so we add one here)
12189       {
12190         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12191         if (soffs <= 0) {
12192           assert (soffs < 0);
12193           soffs++;
12194         } // if
12195         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12196         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12197         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12198         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12199         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12200         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12201         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12202       }
12203
12204       goto release;
12205     }
12206         
12207 //      if(pic16_debug_verbose) {
12208 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12209 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12210 //      }
12211         
12212     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12213     size = AOP_SIZE(IC_RESULT(ic));
12214
12215     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12216     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12217     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12218         
12219     if (size == 3) {
12220       pic16_emitpcode(POC_MOVLW, pcop0);
12221       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12222       pic16_emitpcode(POC_MOVLW, pcop1);
12223       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12224       pic16_emitpcode(POC_MOVLW, pcop2);
12225       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12226     } else
12227     if (size == 2) {
12228       pic16_emitpcode(POC_MOVLW, pcop0);
12229       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12230       pic16_emitpcode(POC_MOVLW, pcop1);
12231     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12232     } else {
12233       pic16_emitpcode(POC_MOVLW, pcop0);
12234       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12235     }
12236
12237     pic16_freeAsmop(left, NULL, ic, FALSE);
12238 release:
12239     pic16_freeAsmop(result,NULL,ic,TRUE);
12240 }
12241
12242
12243 #if 0
12244 /*-----------------------------------------------------------------*/
12245 /* genFarFarAssign - assignment when both are in far space         */
12246 /*-----------------------------------------------------------------*/
12247 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12248 {
12249     int size = AOP_SIZE(right);
12250     int offset = 0;
12251     char *l ;
12252     /* first push the right side on to the stack */
12253     while (size--) {
12254         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12255         MOVA(l);
12256         pic16_emitcode ("push","acc");
12257     }
12258     
12259     pic16_freeAsmop(right,NULL,ic,FALSE);
12260     /* now assign DPTR to result */
12261     pic16_aopOp(result,ic,FALSE);
12262     size = AOP_SIZE(result);
12263     while (size--) {
12264         pic16_emitcode ("pop","acc");
12265         pic16_aopPut(AOP(result),"a",--offset);
12266     }
12267     pic16_freeAsmop(result,NULL,ic,FALSE);
12268         
12269 }
12270 #endif
12271
12272 /*-----------------------------------------------------------------*/
12273 /* genAssign - generate code for assignment                        */
12274 /*-----------------------------------------------------------------*/
12275 static void genAssign (iCode *ic)
12276 {
12277   operand *result, *right;
12278   sym_link *restype, *rtype;
12279   int size, offset,know_W;
12280   unsigned long lit = 0L;
12281
12282   result = IC_RESULT(ic);
12283   right  = IC_RIGHT(ic) ;
12284
12285   FENTRY;
12286   
12287   /* if they are the same */
12288   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12289     return ;
12290
12291   /* reversed order operands are aopOp'ed so that result operand
12292    * is effective in case right is a stack symbol. This maneauver
12293    * allows to use the _G.resDirect flag later */
12294   pic16_aopOp(result,ic,TRUE);
12295   pic16_aopOp(right,ic,FALSE);
12296
12297   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12298
12299   /* if they are the same registers */
12300   if (pic16_sameRegs(AOP(right),AOP(result)))
12301     goto release;
12302
12303   /* if the result is a bit */
12304   if (AOP_TYPE(result) == AOP_CRY) {
12305     /* if the right size is a literal then
12306        we know what the value is */
12307     if (AOP_TYPE(right) == AOP_LIT) {
12308           
12309       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12310                   pic16_popGet(AOP(result),0));
12311
12312       if (((int) operandLitValue(right))) 
12313         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12314                        AOP(result)->aopu.aop_dir,
12315                        AOP(result)->aopu.aop_dir);
12316       else
12317         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12318                        AOP(result)->aopu.aop_dir,
12319                        AOP(result)->aopu.aop_dir);
12320       goto release;
12321     }
12322
12323     /* the right is also a bit variable */
12324     if (AOP_TYPE(right) == AOP_CRY) {
12325       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12326       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12327       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12328
12329       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12330                      AOP(result)->aopu.aop_dir,
12331                      AOP(result)->aopu.aop_dir);
12332       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12333                      AOP(right)->aopu.aop_dir,
12334                      AOP(right)->aopu.aop_dir);
12335       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12336                      AOP(result)->aopu.aop_dir,
12337                      AOP(result)->aopu.aop_dir);
12338       goto release ;
12339     }
12340
12341     /* we need to or */
12342     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12343     pic16_toBoolean(right);
12344     emitSKPZ;
12345     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12346     //pic16_aopPut(AOP(result),"a",0);
12347     goto release ;
12348   }
12349
12350   /* bit variables done */
12351   /* general case */
12352   size = AOP_SIZE(result);
12353   restype = operandType(result);
12354   rtype = operandType(right);
12355   offset = 0 ;
12356
12357   if(AOP_TYPE(right) == AOP_LIT) {
12358     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12359     {
12360       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12361
12362       /* patch tag for literals that are cast to pointers */
12363       if (IS_CODEPTR(restype)) {
12364         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12365         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12366       } else {
12367         if (IS_GENPTR(restype))
12368         {
12369           if (IS_CODEPTR(rtype)) {
12370             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12371             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12372           } else if (PIC_IS_DATA_PTR(rtype)) {
12373             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12374             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12375           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12376             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12377           } else if (IS_PTR(rtype)) {
12378             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12379             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12380           }
12381         }
12382       }
12383     } else {
12384       union {
12385         unsigned long lit_int;
12386         float lit_float;
12387       } info;
12388
12389
12390       if(IS_FIXED16X16(operandType(right))) {
12391         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12392       } else {
12393         /* take care if literal is a float */
12394         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12395         lit = info.lit_int;
12396       }
12397     }
12398   }
12399
12400 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12401 //                      sizeof(unsigned long int), sizeof(float));
12402
12403
12404   if (AOP_TYPE(right) == AOP_REG) {
12405     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12406     while (size--) {
12407       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12408     } // while
12409     goto release;
12410   }
12411
12412   /* when do we have to read the program memory?
12413    * - if right itself is a symbol in code space
12414    *   (we don't care what it points to if it's a pointer)
12415    * - AND right is not a function (we would want its address)
12416    */
12417   if(AOP_TYPE(right) != AOP_LIT
12418         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12419         && !IS_FUNC(OP_SYM_TYPE(right))
12420         && !IS_ITEMP(right))
12421   {
12422         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12423         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12424
12425         // set up table pointer
12426         if(is_LitOp(right)) {
12427 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12428                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12429                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12430                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12431                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12432                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12433                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12434         } else {
12435 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12436                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12437                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12438                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12439                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12440                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12441                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12442         }
12443
12444         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12445         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12446         while(size--) {
12447                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12448                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12449                         pic16_popGet(AOP(result),offset)));
12450                 offset++;
12451         }
12452
12453         /* FIXME: for pointers we need to extend differently (according
12454          * to pointer type DATA/CODE/EEPROM/... :*/
12455         size = getSize(OP_SYM_TYPE(right));
12456         if(AOP_SIZE(result) > size) {
12457                 size = AOP_SIZE(result) - size;
12458                 while(size--) {
12459                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12460                         offset++;
12461                 }
12462         }
12463         goto release;
12464   }
12465
12466 #if 0
12467 /* VR - What is this?! */
12468   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12470     if(aopIdx(AOP(result),0) == 4) {
12471
12472       /* this is a workaround to save value of right into wreg too,
12473        * value of wreg is going to be used later */
12474       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12475       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12476       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12477       goto release;
12478     } else
12479 //      assert(0);
12480       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12481   }
12482 #endif
12483
12484   know_W=-1;
12485   while (size--) {
12486     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12487     if(AOP_TYPE(right) == AOP_LIT) {
12488       if(lit&0xff) {
12489         if(know_W != (lit&0xff))
12490           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12491         know_W = lit&0xff;
12492         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12493       } else
12494         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12495
12496       lit >>= 8;
12497
12498     } else if (AOP_TYPE(right) == AOP_CRY) {
12499       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12500       if(offset == 0) {
12501         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12502         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12503         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12504       }
12505     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12506         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12507         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12508     } else {
12509       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12510
12511       if(!_G.resDirect)         /* use this aopForSym feature */
12512         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12513     }
12514             
12515     offset++;
12516   }
12517   
12518  release:
12519   pic16_freeAsmop (right,NULL,ic,FALSE);
12520   pic16_freeAsmop (result,NULL,ic,TRUE);
12521
12522
12523 /*-----------------------------------------------------------------*/
12524 /* genJumpTab - generates code for jump table                       */
12525 /*-----------------------------------------------------------------*/
12526 static void genJumpTab (iCode *ic)
12527 {
12528   symbol *jtab;
12529   char *l;
12530   pCodeOp *jt_offs;
12531   pCodeOp *jt_offs_hi;
12532   pCodeOp *jt_label;
12533
12534     FENTRY;
12535
12536     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12537     /* get the condition into accumulator */
12538     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12539     MOVA(l);
12540     /* multiply by three */
12541     pic16_emitcode("add","a,acc");
12542     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12543
12544     jtab = newiTempLabel(NULL);
12545     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12546     pic16_emitcode("jmp","@a+dptr");
12547     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12548
12549 #if 0
12550     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12551     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12552     emitSKPNC;
12553     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12554     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12555     pic16_emitpLabel(jtab->key);
12556
12557 #else
12558
12559     jt_offs = pic16_popGetTempReg(0);
12560     jt_offs_hi = pic16_popGetTempReg(1);
12561     jt_label = pic16_popGetLabel (jtab->key);
12562     //fprintf (stderr, "Creating jump table...\n");
12563
12564     // calculate offset into jump table (idx * sizeof (GOTO))
12565     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12566     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12567     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12568     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12569     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12570     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12571     pic16_emitpcode(POC_MOVWF , jt_offs);
12572
12573     // prepare PCLATx (set to first entry in jump table)
12574     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12575     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12576     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12577     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12578     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12579
12580     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12581     pic16_emitpcode(POC_ADDWF , jt_offs);
12582     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12583     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12584     emitSKPNC;
12585     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12586
12587     // release temporaries and prepare jump into table (new PCL --> WREG)
12588     pic16_emitpcode(POC_MOVFW , jt_offs);
12589     pic16_popReleaseTempReg (jt_offs_hi, 1);
12590     pic16_popReleaseTempReg (jt_offs, 0);
12591
12592     // jump into the table
12593     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12594
12595     pic16_emitpLabelFORCE(jtab->key);
12596 #endif
12597
12598     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12599 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12600
12601     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12602     /* now generate the jump labels */
12603     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12604          jtab = setNextItem(IC_JTLABELS(ic))) {
12605 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12606         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12607         
12608     }
12609     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12610
12611 }
12612
12613 /*-----------------------------------------------------------------*/
12614 /* genMixedOperation - gen code for operators between mixed types  */
12615 /*-----------------------------------------------------------------*/
12616 /*
12617   TSD - Written for the PIC port - but this unfortunately is buggy.
12618   This routine is good in that it is able to efficiently promote 
12619   types to different (larger) sizes. Unfortunately, the temporary
12620   variables that are optimized out by this routine are sometimes
12621   used in other places. So until I know how to really parse the 
12622   iCode tree, I'm going to not be using this routine :(.
12623 */
12624 static int genMixedOperation (iCode *ic)
12625 {
12626 #if 0
12627   operand *result = IC_RESULT(ic);
12628   sym_link *ctype = operandType(IC_LEFT(ic));
12629   operand *right = IC_RIGHT(ic);
12630   int ret = 0;
12631   int big,small;
12632   int offset;
12633
12634   iCode *nextic;
12635   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12636
12637   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12638
12639   nextic = ic->next;
12640   if(!nextic)
12641     return 0;
12642
12643   nextright = IC_RIGHT(nextic);
12644   nextleft  = IC_LEFT(nextic);
12645   nextresult = IC_RESULT(nextic);
12646
12647   pic16_aopOp(right,ic,FALSE);
12648   pic16_aopOp(result,ic,FALSE);
12649   pic16_aopOp(nextright,  nextic, FALSE);
12650   pic16_aopOp(nextleft,   nextic, FALSE);
12651   pic16_aopOp(nextresult, nextic, FALSE);
12652
12653   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12654
12655     operand *t = right;
12656     right = nextright;
12657     nextright = t; 
12658
12659     pic16_emitcode(";remove right +","");
12660
12661   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12662 /*
12663     operand *t = right;
12664     right = nextleft;
12665     nextleft = t; 
12666 */
12667     pic16_emitcode(";remove left +","");
12668   } else
12669     return 0;
12670
12671   big = AOP_SIZE(nextleft);
12672   small = AOP_SIZE(nextright);
12673
12674   switch(nextic->op) {
12675
12676   case '+':
12677     pic16_emitcode(";optimize a +","");
12678     /* if unsigned or not an integral type */
12679     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12680       pic16_emitcode(";add a bit to something","");
12681     } else {
12682
12683       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12684
12685       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12686         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12687         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12688       } else
12689         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12690
12691       offset = 0;
12692       while(--big) {
12693
12694         offset++;
12695
12696         if(--small) {
12697           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12698             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12699             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12700           }
12701
12702           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12703           emitSKPNC;
12704           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12705                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12706                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12707           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12708           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12709
12710         } else {
12711           pic16_emitcode("rlf","known_zero,w");
12712
12713           /*
12714             if right is signed
12715               btfsc  right,7
12716                addlw ff
12717           */
12718           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12719             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12720             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12721           } else {
12722             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12723           }
12724         }
12725       }
12726       ret = 1;
12727     }
12728   }
12729   ret = 1;
12730
12731 release:
12732   pic16_freeAsmop(right,NULL,ic,TRUE);
12733   pic16_freeAsmop(result,NULL,ic,TRUE);
12734   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12735   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12736   if(ret)
12737     nextic->generated = 1;
12738
12739   return ret;
12740 #else
12741   return 0;
12742 #endif
12743 }
12744 /*-----------------------------------------------------------------*/
12745 /* genCast - gen code for casting                                  */
12746 /*-----------------------------------------------------------------*/
12747 static void genCast (iCode *ic)
12748 {
12749   operand *result = IC_RESULT(ic);
12750   sym_link *ctype = operandType(IC_LEFT(ic));
12751   sym_link *rtype = operandType(IC_RIGHT(ic));
12752   sym_link *restype = operandType(IC_RESULT(ic));
12753   operand *right = IC_RIGHT(ic);
12754   int size, offset ;
12755
12756
12757     FENTRY;
12758
12759         /* if they are equivalent then do nothing */
12760 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12761 //              return ;
12762
12763         pic16_aopOp(result,ic,FALSE);
12764         pic16_aopOp(right,ic,FALSE) ;
12765
12766         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12767
12768
12769         /* if the result is a bit */
12770         if (AOP_TYPE(result) == AOP_CRY) {
12771         
12772                 /* if the right size is a literal then
12773                  * we know what the value is */
12774                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12775
12776                 if (AOP_TYPE(right) == AOP_LIT) {
12777                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12778                                 pic16_popGet(AOP(result),0));
12779
12780                         if (((int) operandLitValue(right))) 
12781                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12782                                         AOP(result)->aopu.aop_dir,
12783                                         AOP(result)->aopu.aop_dir);
12784                         else
12785                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12786                                         AOP(result)->aopu.aop_dir,
12787                                         AOP(result)->aopu.aop_dir);
12788                         goto release;
12789                 }
12790
12791                 /* the right is also a bit variable */
12792                 if (AOP_TYPE(right) == AOP_CRY) {
12793                         emitCLRC;
12794                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12795
12796                         pic16_emitcode("clrc","");
12797                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12798                                 AOP(right)->aopu.aop_dir,
12799                                 AOP(right)->aopu.aop_dir);
12800                         pic16_aopPut(AOP(result),"c",0);
12801                         goto release ;
12802                 }
12803
12804                 /* we need to or */
12805                 if (AOP_TYPE(right) == AOP_REG) {
12806                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12807                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12808                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12809                 }
12810                 pic16_toBoolean(right);
12811                 pic16_aopPut(AOP(result),"a",0);
12812                 goto release ;
12813         }
12814
12815         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12816           int offset = 1;
12817
12818                 size = AOP_SIZE(result);
12819
12820                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12821
12822                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12823                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12824                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12825
12826                 while (size--)
12827                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12828
12829                 goto release;
12830         }
12831
12832         if(IS_BITFIELD(getSpec(restype))
12833           && IS_BITFIELD(getSpec(rtype))) {
12834           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12835         }
12836         
12837         /* port from pic14 to cope with generic pointers */
12838         if (PIC_IS_TAGGED(restype))
12839         {
12840           operand *result = IC_RESULT(ic);
12841           //operand *left = IC_LEFT(ic);
12842           operand *right = IC_RIGHT(ic);
12843           int tag = 0xff;
12844
12845           /* copy common part */
12846           int max, size = AOP_SIZE(result);
12847           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12848           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12849
12850           max = size;
12851           while (size--)
12852           {
12853             pic16_mov2w (AOP(right), size);
12854             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12855           } // while
12856
12857           /* upcast into generic pointer type? */
12858           if (IS_GENPTR(restype)
12859               && !PIC_IS_TAGGED(rtype)
12860               && (AOP_SIZE(result) > max))
12861           {
12862             /* determine appropriate tag for right */
12863             if (PIC_IS_DATA_PTR(rtype))
12864               tag = GPTR_TAG_DATA;
12865             else if (IS_CODEPTR(rtype))
12866               tag = GPTR_TAG_CODE;
12867             else if (PIC_IS_DATA_PTR(ctype)) {
12868               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12869               tag = GPTR_TAG_DATA;
12870             } else if (IS_CODEPTR(ctype)) {
12871               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12872               tag = GPTR_TAG_CODE;
12873             } else if (IS_PTR(rtype)) {
12874               PERFORM_ONCE(weirdcast,
12875               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12876               );
12877               tag = GPTR_TAG_DATA;
12878             } else {
12879               PERFORM_ONCE(weirdcast,
12880               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12881               );
12882               tag = GPTR_TAG_DATA;
12883             }
12884
12885             assert (AOP_SIZE(result) == 3);
12886             /* zero-extend address... */
12887             for (size = max; size < AOP_SIZE(result)-1; size++)
12888               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12889             /* ...and add tag */
12890             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12891           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12892             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12893             for (size = max; size < AOP_SIZE(result)-1; size++)
12894               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12895             /* add __code tag */
12896             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12897           } else if (AOP_SIZE(result) > max) {
12898             /* extend non-pointers */
12899             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12900             pic16_addSign(result, max, 0);
12901           } // if
12902           goto release;
12903         }
12904
12905         /* if they are the same size : or less */
12906         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12907
12908                 /* if they are in the same place */
12909                 if (pic16_sameRegs(AOP(right),AOP(result)))
12910                         goto release;
12911
12912                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12913 #if 0
12914                 if (IS_PTR_CONST(rtype))
12915 #else
12916                 if (IS_CODEPTR(rtype))
12917 #endif
12918                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12919
12920 #if 0
12921                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12922 #else
12923                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12924 #endif
12925                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12926
12927 #if 0
12928                 if(AOP_TYPE(right) == AOP_IMMD) {
12929                   pCodeOp *pcop0, *pcop1, *pcop2;
12930                   symbol *sym = OP_SYMBOL( right );
12931
12932                         size = AOP_SIZE(result);
12933                         /* low */
12934                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12935                         /* high */
12936                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12937                         /* upper */
12938                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12939         
12940                         if (size == 3) {
12941                                 pic16_emitpcode(POC_MOVLW, pcop0);
12942                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12943                                 pic16_emitpcode(POC_MOVLW, pcop1);
12944                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12945                                 pic16_emitpcode(POC_MOVLW, pcop2);
12946                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12947                         } else
12948                         if (size == 2) {
12949                                 pic16_emitpcode(POC_MOVLW, pcop0);
12950                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12951                                 pic16_emitpcode(POC_MOVLW, pcop1);
12952                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12953                         } else {
12954                                 pic16_emitpcode(POC_MOVLW, pcop0);
12955                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12956                         }
12957                 } else
12958 #endif
12959                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12960                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12961                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12962                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12963                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12964                         if(AOP_SIZE(result) <2)
12965                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12966                 } else {
12967                         /* if they in different places then copy */
12968                         size = AOP_SIZE(result);
12969                         offset = 0 ;
12970                         while (size--) {
12971                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12972                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12973                                 offset++;
12974                         }
12975                 }
12976                 goto release;
12977         }
12978
12979         /* if the result is of type pointer */
12980         if (IS_PTR(ctype)) {
12981           int p_type;
12982           sym_link *type = operandType(right);
12983           sym_link *etype = getSpec(type);
12984
12985                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12986
12987                 /* pointer to generic pointer */
12988                 if (IS_GENPTR(ctype)) {
12989                   char *l = zero;
12990             
12991                         if (IS_PTR(type)) 
12992                                 p_type = DCL_TYPE(type);
12993                         else {
12994                 /* we have to go by the storage class */
12995                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12996
12997 /*              if (SPEC_OCLS(etype)->codesp )  */
12998 /*                  p_type = CPOINTER ;  */
12999 /*              else */
13000 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13001 /*                      p_type = FPOINTER ; */
13002 /*                  else */
13003 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13004 /*                          p_type = PPOINTER; */
13005 /*                      else */
13006 /*                          if (SPEC_OCLS(etype) == idata ) */
13007 /*                              p_type = IPOINTER ; */
13008 /*                          else */
13009 /*                              p_type = POINTER ; */
13010             }
13011                 
13012             /* the first two bytes are known */
13013       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13014             size = GPTRSIZE - 1; 
13015             offset = 0 ;
13016             while (size--) {
13017               if(offset < AOP_SIZE(right)) {
13018                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13019                 pic16_mov2f(AOP(result), AOP(right), offset);
13020 /*
13021                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13022                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13023                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13024                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13025                 } else { 
13026                   
13027                   pic16_aopPut(AOP(result),
13028                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13029                          offset);
13030                 }
13031 */
13032               } else 
13033                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13034               offset++;
13035             }
13036             /* the last byte depending on type */
13037             switch (p_type) {
13038             case IPOINTER:
13039             case POINTER:
13040             case FPOINTER:
13041                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13042                 break;
13043
13044             case CPOINTER:
13045                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13046                 break;
13047
13048             case PPOINTER:
13049               pic16_emitcode(";BUG!? ","%d",__LINE__);
13050                 l = "#0x03";
13051                 break;
13052
13053             case GPOINTER:
13054                 if (GPTRSIZE > AOP_SIZE(right)) {
13055                   // assume __data pointer... THIS MIGHT BE WRONG!
13056                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13057                 } else {
13058                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13059                 }
13060               break;
13061               
13062             default:
13063                 /* this should never happen */
13064                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13065                        "got unknown pointer type");
13066                 exit(1);
13067             }
13068             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13069             goto release ;
13070         }
13071         
13072         
13073         assert( 0 );
13074         /* just copy the pointers */
13075         size = AOP_SIZE(result);
13076         offset = 0 ;
13077         while (size--) {
13078             pic16_aopPut(AOP(result),
13079                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13080                    offset);
13081             offset++;
13082         }
13083         goto release ;
13084     }
13085     
13086
13087
13088     /* so we now know that the size of destination is greater
13089     than the size of the source.
13090     Now, if the next iCode is an operator then we might be
13091     able to optimize the operation without performing a cast.
13092     */
13093     if(genMixedOperation(ic))
13094       goto release;
13095
13096     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13097     
13098     /* we move to result for the size of source */
13099     size = AOP_SIZE(right);
13100     offset = 0 ;
13101
13102     while (size--) {
13103       if(!_G.resDirect)
13104         pic16_mov2f(AOP(result), AOP(right), offset);
13105       offset++;
13106     }
13107
13108     /* now depending on the sign of the destination */
13109     size = AOP_SIZE(result) - AOP_SIZE(right);
13110     /* if unsigned or not an integral type */
13111     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13112       while (size--)
13113         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13114     } else {
13115       /* we need to extend the sign :( */
13116
13117       if(size == 1) {
13118         /* Save one instruction of casting char to int */
13119         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13120         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13121         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13122       } else {
13123         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13124
13125         if(offset)
13126           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13127         else
13128           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13129         
13130         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13131
13132         while (size--)
13133           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13134       }
13135     }
13136
13137 release:
13138     pic16_freeAsmop(right,NULL,ic,TRUE);
13139     pic16_freeAsmop(result,NULL,ic,TRUE);
13140
13141 }
13142
13143 /*-----------------------------------------------------------------*/
13144 /* genDjnz - generate decrement & jump if not zero instrucion      */
13145 /*-----------------------------------------------------------------*/
13146 static int genDjnz (iCode *ic, iCode *ifx)
13147 {
13148     symbol *lbl, *lbl1;
13149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13150
13151     if (!ifx)
13152         return 0;
13153     
13154     /* if the if condition has a false label
13155        then we cannot save */
13156     if (IC_FALSE(ifx))
13157         return 0;
13158
13159     /* if the minus is not of the form 
13160        a = a - 1 */
13161     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13162         !IS_OP_LITERAL(IC_RIGHT(ic)))
13163         return 0;
13164
13165     if (operandLitValue(IC_RIGHT(ic)) != 1)
13166         return 0;
13167
13168     /* if the size of this greater than one then no
13169        saving */
13170     if (getSize(operandType(IC_RESULT(ic))) > 1)
13171         return 0;
13172
13173     /* otherwise we can save BIG */
13174     lbl = newiTempLabel(NULL);
13175     lbl1= newiTempLabel(NULL);
13176
13177     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13178     
13179     if (IS_AOP_PREG(IC_RESULT(ic))) {
13180         pic16_emitcode("dec","%s",
13181                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13182         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13183         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13184     } else {    
13185
13186
13187       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13188       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13189
13190       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13191       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13192
13193     }
13194     
13195     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13196     ifx->generated = 1;
13197     return 1;
13198 }
13199
13200 /*-----------------------------------------------------------------*/
13201 /* genReceive - generate code for a receive iCode                  */
13202 /*-----------------------------------------------------------------*/
13203 static void genReceive (iCode *ic)
13204 {    
13205
13206   FENTRY;
13207
13208 #if 0
13209   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13210         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13211 #endif
13212 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13213
13214   if (isOperandInFarSpace(IC_RESULT(ic))
13215       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13216           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13217
13218     int size = getSize(operandType(IC_RESULT(ic)));
13219     int offset =  pic16_fReturnSizePic - size;
13220
13221       assert( 0 );
13222       while (size--) {
13223         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13224                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13225                       offset++;
13226         }
13227
13228       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13229
13230       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13231       size = AOP_SIZE(IC_RESULT(ic));
13232       offset = 0;
13233       while (size--) {
13234         pic16_emitcode ("pop","acc");
13235         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13236       }
13237   } else {
13238     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13239     _G.accInUse++;
13240     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13241     _G.accInUse--;
13242
13243     /* set pseudo stack pointer to where it should be - dw*/
13244     GpsuedoStkPtr = ic->parmBytes;
13245
13246     /* setting GpsuedoStkPtr has side effects here: */
13247     assignResultValue(IC_RESULT(ic), 0);
13248   }
13249
13250   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13251 }
13252
13253 /*-----------------------------------------------------------------*/
13254 /* genDummyRead - generate code for dummy read of volatiles        */
13255 /*-----------------------------------------------------------------*/
13256 static void
13257 genDummyRead (iCode * ic)
13258 {
13259   operand *op;
13260   int i;
13261
13262   op = IC_RIGHT(ic);
13263   if (op && IS_SYMOP(op)) {
13264     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13265       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13266       return;
13267     }
13268     pic16_aopOp (op, ic, FALSE);
13269     for (i=0; i < AOP_SIZE(op); i++) {
13270       // may need to protect this from the peepholer -- this is not nice but works...
13271       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13272       pic16_mov2w (AOP(op),i);
13273       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13274     } // for i
13275     pic16_freeAsmop (op, NULL, ic, TRUE);
13276   } else if (op) {
13277     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13278   } // if
13279 }
13280
13281 /*-----------------------------------------------------------------*/
13282 /* genpic16Code - generate code for pic16 based controllers        */
13283 /*-----------------------------------------------------------------*/
13284 /*
13285  * At this point, ralloc.c has gone through the iCode and attempted
13286  * to optimize in a way suitable for a PIC. Now we've got to generate
13287  * PIC instructions that correspond to the iCode.
13288  *
13289  * Once the instructions are generated, we'll pass through both the
13290  * peep hole optimizer and the pCode optimizer.
13291  *-----------------------------------------------------------------*/
13292
13293 void genpic16Code (iCode *lic)
13294 {
13295   iCode *ic;
13296   int cln = 0;
13297
13298     lineHead = lineCurr = NULL;
13299
13300     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13301     pic16_addpBlock(pb);
13302
13303 #if 0
13304     /* if debug information required */
13305     if (options.debug && currFunc) {
13306       if (currFunc) {
13307         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13308       }
13309     }
13310 #endif
13311
13312     for (ic = lic ; ic ; ic = ic->next ) {
13313
13314       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13315       if ( cln != ic->lineno ) {
13316         if ( options.debug ) {
13317           debugFile->writeCLine (ic);
13318         }
13319         
13320         if(!options.noCcodeInAsm) {
13321           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13322               printCLine(ic->filename, ic->lineno)));
13323         }
13324
13325         cln = ic->lineno ;
13326       }
13327         
13328       if(options.iCodeInAsm) {
13329         char *l;
13330
13331           /* insert here code to print iCode as comment */
13332           l = Safe_strdup(printILine(ic));
13333           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13334       }
13335         
13336       /* if the result is marked as
13337        * spilt and rematerializable or code for
13338        * this has already been generated then
13339        * do nothing */
13340       if (resultRemat(ic) || ic->generated ) 
13341         continue ;
13342         
13343       /* depending on the operation */
13344       switch (ic->op) {
13345         case '!' :
13346           pic16_genNot(ic);
13347           break;
13348             
13349         case '~' :
13350           pic16_genCpl(ic);
13351           break;
13352             
13353         case UNARYMINUS:
13354           genUminus (ic);
13355           break;
13356             
13357         case IPUSH:
13358           genIpush (ic);
13359           break;
13360             
13361         case IPOP:
13362           /* IPOP happens only when trying to restore a 
13363            * spilt live range, if there is an ifx statement
13364            * following this pop then the if statement might
13365            * be using some of the registers being popped which
13366            * would destroy the contents of the register so
13367            * we need to check for this condition and handle it */
13368            if (ic->next
13369              && ic->next->op == IFX
13370              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13371                genIfx (ic->next,ic);
13372           else
13373             genIpop (ic);
13374           break; 
13375             
13376         case CALL:
13377           genCall (ic);
13378           break;
13379             
13380         case PCALL:
13381           genPcall (ic);
13382           break;
13383             
13384         case FUNCTION:
13385           genFunction (ic);
13386           break;
13387             
13388         case ENDFUNCTION:
13389           genEndFunction (ic);
13390           break;
13391             
13392         case RETURN:
13393           genRet (ic);
13394           break;
13395             
13396         case LABEL:
13397           genLabel (ic);
13398           break;
13399             
13400         case GOTO:
13401           genGoto (ic);
13402           break;
13403             
13404         case '+' :
13405           pic16_genPlus (ic) ;
13406           break;
13407             
13408         case '-' :
13409           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13410             pic16_genMinus (ic);
13411           break;
13412
13413         case '*' :
13414           genMult (ic);
13415           break;
13416             
13417         case '/' :
13418           genDiv (ic) ;
13419           break;
13420             
13421         case '%' :
13422           genMod (ic);
13423           break;
13424             
13425         case '>' :
13426           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13427           break;
13428             
13429         case '<' :
13430           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13431           break;
13432             
13433         case LE_OP:
13434         case GE_OP:
13435         case NE_OP:
13436           /* note these two are xlated by algebraic equivalence
13437            * during parsing SDCC.y */
13438           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13439             "got '>=' or '<=' shouldn't have come here");
13440           break;
13441
13442         case EQ_OP:
13443           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13444           break;            
13445             
13446         case AND_OP:
13447           genAndOp (ic);
13448           break;
13449             
13450         case OR_OP:
13451           genOrOp (ic);
13452           break;
13453             
13454         case '^' :
13455           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13456           break;
13457             
13458         case '|' :
13459           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13460           break;
13461             
13462         case BITWISEAND:
13463           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13464           break;
13465             
13466         case INLINEASM:
13467           genInline (ic);
13468           break;
13469             
13470         case RRC:
13471           genRRC (ic);
13472           break;
13473             
13474         case RLC:
13475           genRLC (ic);
13476           break;
13477             
13478         case GETHBIT:
13479           genGetHbit (ic);
13480           break;
13481             
13482         case LEFT_OP:
13483           genLeftShift (ic);
13484           break;
13485             
13486         case RIGHT_OP:
13487           genRightShift (ic);
13488           break;
13489             
13490         case GET_VALUE_AT_ADDRESS:
13491           genPointerGet(ic);
13492           break;
13493             
13494         case '=' :
13495           if (POINTER_SET(ic))
13496             genPointerSet(ic);
13497           else
13498             genAssign(ic);
13499           break;
13500             
13501         case IFX:
13502           genIfx (ic,NULL);
13503           break;
13504             
13505         case ADDRESS_OF:
13506           genAddrOf (ic);
13507           break;
13508             
13509         case JUMPTABLE:
13510           genJumpTab (ic);
13511           break;
13512             
13513         case CAST:
13514           genCast (ic);
13515           break;
13516             
13517         case RECEIVE:
13518           genReceive(ic);
13519           break;
13520             
13521         case SEND:
13522           addSet(&_G.sendSet,ic);
13523           break;
13524
13525         case DUMMY_READ_VOLATILE:
13526           genDummyRead (ic);
13527           break;
13528
13529         default :
13530           ic = ic;
13531       }
13532     }
13533
13534
13535     /* now we are ready to call the
13536        peep hole optimizer */
13537     if (!options.nopeep)
13538       peepHole (&lineHead);
13539
13540     /* now do the actual printing */
13541     printLine (lineHead, codeOutFile);
13542
13543 #ifdef PCODE_DEBUG
13544     DFPRINTF((stderr,"printing pBlock\n\n"));
13545     pic16_printpBlock(stdout,pb);
13546 #endif
13547
13548     return;
13549 }
13550