04a9a1c06930af284d9a4575db7264a01fbd9056
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   Bug Fixes  -  Borut Razem <borut.razem AT siol.net> (2007)
12
13   This program is free software; you can redistribute it and/or modify it
14   under the terms of the GNU General Public License as published by the
15   Free Software Foundation; either version 2, or (at your option) any
16   later version.
17
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27   In other words, you are welcome to use, share and improve this program.
28   You are forbidden to forbid anyone else to use, share and improve
29   what you give them.   Help stamp out software-hoarding!
30
31   Notes:
32   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
33                 Made everything static
34 -------------------------------------------------------------------------*/
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include "SDCCglobl.h"
41 #include "newalloc.h"
42
43 #include "common.h"
44 #include "SDCCpeeph.h"
45 #include "ralloc.h"
46 #include "pcode.h"
47 #include "gen.h"
48 #include "genutils.h"
49 #include "device.h"
50 #include "main.h"
51 #include "glue.h"
52
53 /* Set the following to 1 to enable the slower/bigger
54  * but more robust generic shifting routine (which also
55  * operates correctly with negative shift values). */
56 #define USE_GENERIC_SIGNED_SHIFT 1
57
58 /* Set the following to 1 to enable the new
59  * stripped down genCmp version.
60  * This version should be easier to understand,
61  * more reliable and (sigh) slighly slower. */
62 #define USE_SIMPLE_GENCMP 1
63
64 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
65 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
67 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
68 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
69
70 /* If you change these, you also have to update the library files
71  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
72 #define GPTR_TAG_DATA   0x80
73 #define GPTR_TAG_EEPROM 0x40
74 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
75
76 /* Wrapper to execute `code' at most once. */
77 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
78
79 void pic16_genMult8X8_n (operand *, operand *,operand *);
80 #if 0
81 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
83 void pic16_genMult16X16_16(operand *, operand *, operand *);
84 void pic16_genMult32X32_32(operand *, operand *, operand *);
85 #endif
86 pCode *pic16_AssembleLine(char *line, int peeps);
87 extern void pic16_printpBlock(FILE *of, pBlock *pb);
88 static asmop *newAsmop (short type);
89 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
90 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
91 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
92 static pCodeOp *pic16_popRegFromIdx(int rIdx);
93
94 //static int aopIdx (asmop *aop, int offset);
95
96 int pic16_labelOffset=0;
97 extern int pic16_debug_verbose;
98 #if !(USE_GENERIC_SIGNED_SHIFT)
99 static int optimized_for_speed = 0;
100 #endif
101 /*
102   hack hack
103
104 */
105
106 extern set *externs;
107
108 /* max_key keeps track of the largest label number used in
109    a function. This is then used to adjust the label offset
110    for the next function.
111 */
112 static int max_key=0;
113 static int GpsuedoStkPtr=0;
114
115 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
116
117 const char *pic16_AopType(short type);
118 static iCode *ifxForOp ( operand *op, iCode *ic );
119
120 void pic16_pushpCodeOp(pCodeOp *pcop);
121 void pic16_poppCodeOp(pCodeOp *pcop);
122
123 static bool is_LitOp(operand *op);
124 static bool is_LitAOp(asmop *aop);
125
126
127 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
128
129 /* set the following macro to 1 to enable passing the
130  * first byte of functions parameters via WREG */
131 #define USE_WREG_IN_FUNC_PARAMS 0
132
133
134 /* this is the down and dirty file with all kinds of
135    kludgy & hacky stuff. This is what it is all about
136    CODE GENERATION for a specific MCU . some of the
137    routines may be reusable, will have to see */
138
139 static char *zero = "#0x00";
140 static char *one  = "#0x01";
141 //static char *spname = "sp";
142
143
144 /*
145  * Function return value policy (MSB-->LSB):
146  *  8 bits      -> WREG
147  * 16 bits      -> PRODL:WREG
148  * 24 bits      -> PRODH:PRODL:WREG
149  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
150  * >32 bits     -> on stack, and FSR0 points to the beginning
151  *
152  */
153
154
155 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
156 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
157 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
158 static char **fReturn = fReturnpic16;
159
160 static char *accUse[] = {"WREG"};
161
162 //static short rbank = -1;
163
164 static struct {
165     short r0Pushed;
166     short r1Pushed;
167     short fsr0Pushed;
168     short accInUse;
169     short inLine;
170     short debugLine;
171     short nRegsSaved;
172     short ipushRegs;
173     set *sendSet;
174     set *stackRegSet;
175     int usefastretfie;
176     bitVect *fregsUsed;                 /* registers used in function */
177     bitVect *sregsAlloc;
178     set *sregsAllocSet;                 /* registers used to store stack variables */
179     int stack_lat;                      /* stack offset latency */
180     int resDirect;
181     int useWreg;                        /* flag when WREG is used to pass function parameter */
182 } _G;
183
184 extern int pic16_ptrRegReq ;
185 extern int pic16_nRegs;
186 extern struct dbuf_s *codeOutBuf;
187 //static void saverbank (int, iCode *,bool);
188
189 static lineNode *lineHead = NULL;
190 static lineNode *lineCurr = NULL;
191
192 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
193 0xE0, 0xC0, 0x80, 0x00};
194 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
195 0x07, 0x03, 0x01, 0x00};
196
197 static  pBlock *pb;
198
199 /*-----------------------------------------------------------------*/
200 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
201 /*                 exponent of 2 is returned, otherwise -1 is      */
202 /*                 returned.                                       */
203 /* note that this is similar to the function `powof2' in SDCCsymt  */
204 /* if(n == 2^y)                                                    */
205 /*   return y;                                                     */
206 /* return -1;                                                      */
207 /*-----------------------------------------------------------------*/
208 int pic16_my_powof2 (unsigned long num)
209 {
210   if(num) {
211     if( (num & (num-1)) == 0) {
212       int nshifts = -1;
213       while(num) {
214         num>>=1;
215         nshifts++;
216       }
217       return nshifts;
218     }
219   }
220
221   return -1;
222 }
223
224 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
225 {
226   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
227                        line_no,
228                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
229                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
230                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
231                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
232                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
233                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
234                        ((result) ? AOP_SIZE(result) : 0));
235 }
236
237 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
238 {
239
240   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
241                        line_no,
242                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
243                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
244                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
245                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
246                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
247                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
248
249 }
250
251 void pic16_emitpcomment (char *fmt, ...)
252 {
253     va_list ap;
254     char lb[INITIAL_INLINEASM];
255     unsigned char *lbp = (unsigned char *)lb;
256
257     va_start(ap,fmt);
258
259     lb[0] = ';';
260     vsprintf(lb+1,fmt,ap);
261
262     while (isspace(*lbp)) lbp++;
263
264     if (lbp && *lbp)
265         lineCurr = (lineCurr ?
266                     connectLine(lineCurr,newLineNode(lb)) :
267                     (lineHead = newLineNode(lb)));
268     lineCurr->isInline = _G.inLine;
269     lineCurr->isDebug  = _G.debugLine;
270     lineCurr->isComment = 1;
271
272     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
273     va_end(ap);
274
275 //      fprintf(stderr, "%s\n", lb);
276 }
277
278 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
279 {
280     va_list ap;
281     char lb[INITIAL_INLINEASM];
282     unsigned char *lbp = (unsigned char *)lb;
283
284     if(!pic16_debug_verbose)
285       return;
286
287     va_start(ap,fmt);
288
289     if (inst && *inst) {
290         if (fmt && *fmt)
291             sprintf(lb,"%s\t",inst);
292         else
293             sprintf(lb,"%s",inst);
294         vsprintf(lb+(strlen(lb)),fmt,ap);
295     }  else
296         vsprintf(lb,fmt,ap);
297
298     while (isspace(*lbp)) lbp++;
299
300     if (lbp && *lbp)
301         lineCurr = (lineCurr ?
302                     connectLine(lineCurr,newLineNode(lb)) :
303                     (lineHead = newLineNode(lb)));
304     lineCurr->isInline = _G.inLine;
305     lineCurr->isDebug  = _G.debugLine;
306
307     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
308     va_end(ap);
309
310 //      fprintf(stderr, "%s\n", lb);
311 }
312
313
314
315 void pic16_emitpLabel(int key)
316 {
317   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
318 }
319
320 void pic16_emitpLabelFORCE(int key)
321 {
322   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
323 }
324
325 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
326  * NEVER call pic16_emitpcode_real directly, please... */
327 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
328 {
329
330   if(pcop)
331     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
332   else
333     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
334 }
335
336 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
337 {
338   if(pcop)
339     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
340   else
341     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
342 }
343
344 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
345 {
346
347   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
348
349 }
350
351
352 #if 1
353 #define pic16_emitcode  DEBUGpic16_emitcode
354 #else
355 /*-----------------------------------------------------------------*/
356 /* pic16_emitcode - writes the code into a file : for now it is simple    */
357 /*-----------------------------------------------------------------*/
358 void pic16_emitcode (char *inst,char *fmt, ...)
359 {
360     va_list ap;
361     char lb[INITIAL_INLINEASM];
362     unsigned char *lbp = lb;
363
364     va_start(ap,fmt);
365
366     if (inst && *inst) {
367         if (fmt && *fmt)
368             sprintf(lb,"%s\t",inst);
369         else
370             sprintf(lb,"%s",inst);
371         vsprintf(lb+(strlen(lb)),fmt,ap);
372     }  else
373         vsprintf(lb,fmt,ap);
374
375     while (isspace(*lbp)) lbp++;
376
377     if (lbp && *lbp)
378         lineCurr = (lineCurr ?
379                     connectLine(lineCurr,newLineNode(lb)) :
380                     (lineHead = newLineNode(lb)));
381     lineCurr->isInline = _G.inLine;
382     lineCurr->isDebug  = _G.debugLine;
383     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
384     lineCurr->isComment = (*lbp == ';');
385
386 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
387
388 //    if(pic16_debug_verbose)
389 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
390
391     va_end(ap);
392 }
393 #endif
394
395
396 /*-----------------------------------------------------------------*/
397 /* pic16_emitDebuggerSymbol - associate the current code location  */
398 /*   with a debugger symbol                                        */
399 /*-----------------------------------------------------------------*/
400 void
401 pic16_emitDebuggerSymbol (char * debugSym)
402 {
403   _G.debugLine = 1;
404   pic16_emitcode (";", "%s ==.", debugSym);
405   _G.debugLine = 0;
406 }
407
408
409 /*-----------------------------------------------------------------*/
410 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
411 /*-----------------------------------------------------------------*/
412 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
413 {
414 //    bool r0iu = FALSE , r1iu = FALSE;
415 //    bool r0ou = FALSE , r1ou = FALSE;
416     bool fsr0iu = FALSE, fsr0ou;
417     bool fsr2iu = FALSE, fsr2ou;
418
419     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
420
421
422     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
423     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
424
425     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
426     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
427
428     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
429         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
430         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
431     }
432
433     if(!fsr0iu && !fsr0ou) {
434         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
435         (*aopp)->type = AOP_FSR0;
436
437         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
438
439       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
440     }
441
442 #if 0
443     /* no usage of FSR2 */
444     if(!fsr2iu && !fsr2ou) {
445         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
446         (*aopp)->type = AOP_FSR2;
447
448       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
449     }
450 #endif
451
452     /* now we know they both have usage */
453     /* if fsr0 not used in this instruction */
454     if (!fsr0iu) {
455         if (!_G.fsr0Pushed) {
456                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
457                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
458                 _G.fsr0Pushed++;
459         }
460
461         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
462         (*aopp)->type = AOP_FSR0;
463
464 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
465
466       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
467     }
468
469
470     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
471     assert( 0 );
472
473     return NULL;
474 #if 0
475     /* the logic: if r0 & r1 used in the instruction
476     then we are in trouble otherwise */
477
478     /* first check if r0 & r1 are used by this
479     instruction, in which case we are in trouble */
480     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
481         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
482     {
483         goto endOfWorld;
484     }
485
486     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
487     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
488
489     /* if no usage of r0 then return it */
490     if (!r0iu && !r0ou) {
491         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
492         (*aopp)->type = AOP_R0;
493
494         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
495     }
496
497     /* if no usage of r1 then return it */
498     if (!r1iu && !r1ou) {
499         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
500         (*aopp)->type = AOP_R1;
501
502         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
503     }
504
505     /* now we know they both have usage */
506     /* if r0 not used in this instruction */
507     if (!r0iu) {
508         /* push it if not already pushed */
509         if (!_G.r0Pushed) {
510           //pic16_emitcode ("push","%s",
511           //          pic16_regWithIdx(R0_IDX)->dname);
512             _G.r0Pushed++ ;
513         }
514
515         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
516         (*aopp)->type = AOP_R0;
517
518         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
519     }
520
521     /* if r1 not used then */
522
523     if (!r1iu) {
524         /* push it if not already pushed */
525         if (!_G.r1Pushed) {
526           //pic16_emitcode ("push","%s",
527           //          pic16_regWithIdx(R1_IDX)->dname);
528             _G.r1Pushed++ ;
529         }
530
531         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
532         (*aopp)->type = AOP_R1;
533         return pic16_regWithIdx(R1_IDX);
534     }
535
536 endOfWorld :
537     /* I said end of world but not quite end of world yet */
538     /* if this is a result then we can push it on the stack*/
539     if (result) {
540         (*aopp)->type = AOP_STK;
541         return NULL;
542     }
543
544     /* other wise this is true end of the world */
545     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
546            "getFreePtr should never reach here");
547     exit(0);
548 #endif
549 }
550
551 /*-----------------------------------------------------------------*/
552 /* newAsmop - creates a new asmOp                                  */
553 /*-----------------------------------------------------------------*/
554 static asmop *newAsmop (short type)
555 {
556     asmop *aop;
557
558     aop = Safe_calloc(1,sizeof(asmop));
559     aop->type = type;
560     return aop;
561 }
562
563 static void genSetDPTR(int n)
564 {
565     if (!n)
566     {
567         pic16_emitcode(";", "Select standard DPTR");
568         pic16_emitcode("mov", "dps, #0x00");
569     }
570     else
571     {
572         pic16_emitcode(";", "Select alternate DPTR");
573         pic16_emitcode("mov", "dps, #0x01");
574     }
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* resolveIfx - converts an iCode ifx into a form more useful for  */
579 /*              generating code                                    */
580 /*-----------------------------------------------------------------*/
581 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
582 {
583   FENTRY2;
584
585 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
586
587   if(!resIfx)
588     return;
589
590
591   resIfx->condition = 1;    /* assume that the ifx is true */
592   resIfx->generated = 0;    /* indicate that the ifx has not been used */
593
594   if(!ifx) {
595     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
596
597 #if 1
598     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
599                         __FUNCTION__,__LINE__,resIfx->lbl->key);
600 #endif
601
602   } else {
603     if(IC_TRUE(ifx)) {
604       resIfx->lbl = IC_TRUE(ifx);
605     } else {
606       resIfx->lbl = IC_FALSE(ifx);
607       resIfx->condition = 0;
608     }
609
610 #if 1
611     if(IC_TRUE(ifx))
612       DEBUGpic16_emitcode("; +++","ifx true is non-null");
613     else
614       DEBUGpic16_emitcode("; +++","ifx true is null");
615     if(IC_FALSE(ifx))
616       DEBUGpic16_emitcode("; +++","ifx false is non-null");
617     else
618       DEBUGpic16_emitcode("; +++","ifx false is null");
619 #endif
620   }
621
622   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
623
624 }
625 #if 0
626 /*-----------------------------------------------------------------*/
627 /* pointerCode - returns the code for a pointer type               */
628 /*-----------------------------------------------------------------*/
629 static int pointerCode (sym_link *etype)
630 {
631
632     return PTR_TYPE(SPEC_OCLS(etype));
633
634 }
635 #endif
636
637 /*-----------------------------------------------------------------*/
638 /* aopForSym - for a true symbol                                   */
639 /*-----------------------------------------------------------------*/
640 static asmop *aopForSym (iCode *ic, operand *op, bool result)
641 {
642     symbol *sym=OP_SYMBOL(op);
643     asmop *aop;
644     memmap *space= SPEC_OCLS(sym->etype);
645
646     FENTRY2;
647
648     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
649
650 //    sym = OP_SYMBOL(op);
651
652     /* if already has one */
653     if (sym->aop) {
654             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
655         return sym->aop;
656     }
657
658 #if 0
659     /* if symbol was initially placed onStack then we must re-place it
660      * to direct memory, since pic16 does not have a specific stack */
661     if(sym->onStack) {
662         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
663     }
664 #endif
665
666
667 #if 0
668     if(sym->iaccess) {
669       if(space->paged) {
670         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
671
672         sym->aop = aop = newAsmop (AOP_PAGED);
673         aop->aopu.aop_dir = sym->rname ;
674         aop->size = getSize(sym->type);
675         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
676         pic16_allocDirReg( IC_LEFT(ic) );
677         return aop;
678       }
679       assert( 0 );
680     }
681 #endif
682
683 #if 1
684     /* assign depending on the storage class */
685     /* if it is on the stack or indirectly addressable */
686     /* space we need to assign either r0 or r1 to it   */
687     if (sym->onStack)   // || sym->iaccess)
688     {
689       pCodeOp *pcop[4];
690       int i;
691
692         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
693                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
694
695         /* acquire a temporary register -- it is saved in function */
696
697         sym->aop = aop = newAsmop(AOP_STA);
698         aop->aopu.stk.stk = sym->stack;
699         aop->size = getSize(sym->type);
700
701
702         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
703         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
704           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
705 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
706
707           for(i=0;i<aop->size;i++)
708             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
709             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
710         } else
711         if(1 && ic->op == SEND) {
712
713           /* if SEND do the send here */
714           _G.resDirect = 1;
715         } else {
716 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
717           for(i=0;i<aop->size;i++) {
718             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
719             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
720           }
721         }
722
723
724 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
725
726 #if 1
727         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
728
729         // we do not need to load the value if it is to be defined...
730         if (result) return aop;
731
732         if(_G.accInUse) {
733                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
734         }
735
736         for(i=0;i<aop->size;i++) {
737
738           /* initialise for stack access via frame pointer */
739           // operands on stack are accessible via "{FRAME POINTER} + index" with index
740           // starting at 2 for arguments and growing from 0 downwards for
741           // local variables (index == 0 is not assigned so we add one here)
742           {
743             int soffs = sym->stack;
744             if (soffs <= 0) {
745               assert (soffs < 0);
746               soffs++;
747             } // if
748
749             if(1 && ic->op == SEND) {
750               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
751               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
752                     pic16_popCopyReg( pic16_frame_plusw ),
753                     pic16_popCopyReg(pic16_stack_postdec )));
754             } else {
755               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
756               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
757                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
758             }
759           }
760         }
761
762         if(_G.accInUse) {
763                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
764         }
765
766         return (aop);
767 #endif
768
769 #if 0
770         /* now assign the address of the variable to
771         the pointer register */
772         if (aop->type != AOP_STK) {
773
774             if (sym->onStack) {
775                     if ( _G.accInUse )
776                         pic16_emitcode("push","acc");
777
778                     pic16_emitcode("mov","a,_bp");
779                     pic16_emitcode("add","a,#0x%02x",
780                              ((sym->stack < 0) ?
781                               ((char)(sym->stack - _G.nRegsSaved )) :
782                               ((char)sym->stack)) & 0xff);
783                     pic16_emitcode("mov","%s,a",
784                              aop->aopu.aop_ptr->name);
785
786                     if ( _G.accInUse )
787                         pic16_emitcode("pop","acc");
788             } else
789                 pic16_emitcode("mov","%s,#%s",
790                          aop->aopu.aop_ptr->name,
791                          sym->rname);
792             aop->paged = space->paged;
793         } else
794             aop->aopu.aop_stk = sym->stack;
795         return aop;
796 #endif
797
798     }
799 #endif
800
801 #if 0
802     if (sym->onStack && options.stack10bit)
803     {
804         /* It's on the 10 bit stack, which is located in
805          * far data space.
806          */
807
808       //DEBUGpic16_emitcode(";","%d",__LINE__);
809
810         if ( _G.accInUse )
811                 pic16_emitcode("push","acc");
812
813         pic16_emitcode("mov","a,_bp");
814         pic16_emitcode("add","a,#0x%02x",
815                  ((sym->stack < 0) ?
816                    ((char)(sym->stack - _G.nRegsSaved )) :
817                    ((char)sym->stack)) & 0xff);
818
819         genSetDPTR(1);
820         pic16_emitcode ("mov","dpx1,#0x40");
821         pic16_emitcode ("mov","dph1,#0x00");
822         pic16_emitcode ("mov","dpl1, a");
823         genSetDPTR(0);
824
825         if ( _G.accInUse )
826             pic16_emitcode("pop","acc");
827
828         sym->aop = aop = newAsmop(AOP_DPTR2);
829         aop->size = getSize(sym->type);
830         return aop;
831     }
832 #endif
833
834 #if 1
835     /* special case for a function */
836     if (IS_FUNC(sym->type)) {
837         sym->aop = aop = newAsmop(AOP_PCODE);
838         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
839         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
840         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
841         PCOI(aop->aopu.pcop)->index = 0;
842         aop->size = FPTRSIZE;
843         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
844         return aop;
845     }
846 #endif
847
848
849
850     //DEBUGpic16_emitcode(";","%d",__LINE__);
851     /* if in bit space */
852     if (IN_BITSPACE(space)) {
853         sym->aop = aop = newAsmop (AOP_CRY);
854         aop->aopu.aop_dir = sym->rname ;
855         aop->size = getSize(sym->type);
856         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
857         return aop;
858     }
859     /* if it is in direct space */
860     if (IN_DIRSPACE(space)) {
861                 if(!strcmp(sym->rname, "_WREG")) {
862                         sym->aop = aop = newAsmop (AOP_ACC);
863                         aop->size = getSize(sym->type);         /* should always be 1 */
864                         assert(aop->size == 1);
865                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
866                         return (aop);
867                 } else {
868                         sym->aop = aop = newAsmop (AOP_DIR);
869                 aop->aopu.aop_dir = sym->rname ;
870             aop->size = getSize(sym->type);
871                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
872                         pic16_allocDirReg( IC_LEFT(ic) );
873                         return (aop);
874                 }
875         }
876
877     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
878         sym->aop = aop = newAsmop (AOP_DIR);
879         aop->aopu.aop_dir = sym->rname ;
880         aop->size = getSize(sym->type);
881         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
882         pic16_allocDirReg( IC_LEFT(ic) );
883         return aop;
884     }
885
886
887     /* only remaining is far space */
888     sym->aop = aop = newAsmop(AOP_PCODE);
889
890 /* change the next if to 1 to revert to good old immediate code */
891         if(IN_CODESPACE(space)) {
892                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
893                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
894                 PCOI(aop->aopu.pcop)->index = 0;
895         } else {
896                 /* try to allocate via direct register */
897                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
898 //              aop->size = getSize( sym->type );
899         }
900
901         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
902                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
903
904 #if 0
905         if(!pic16_allocDirReg (IC_LEFT(ic)))
906                 return NULL;
907 #endif
908
909         if(IN_DIRSPACE( space ))
910                 aop->size = PTRSIZE;
911         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
912                 aop->size = FPTRSIZE;
913         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
914         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
915         else if(sym->onStack) {
916                 aop->size = PTRSIZE;
917         } else {
918           if(SPEC_SCLS(sym->etype) == S_PDATA) {
919             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
920             aop->size = FPTRSIZE;
921           } else
922                 assert( 0 );
923         }
924
925     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
926
927     /* if it is in code space */
928     if (IN_CODESPACE(space))
929         aop->code = 1;
930
931     return aop;
932 }
933
934 /*-----------------------------------------------------------------*/
935 /* aopForRemat - rematerialzes an object                           */
936 /*-----------------------------------------------------------------*/
937 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
938 {
939   symbol *sym = OP_SYMBOL(op);
940   operand *refop;
941   iCode *ic = NULL, *oldic;
942   asmop *aop = newAsmop(AOP_PCODE);
943   int val = 0;
944   int offset = 0;
945   int viaimmd=0;
946
947     FENTRY2;
948
949         ic = sym->rematiCode;
950
951         if(IS_OP_POINTER(op)) {
952                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
953         }
954
955 //    if(!result)               /* fixme-vr */
956         for (;;) {
957                 oldic = ic;
958
959 //              chat *iLine = printILine(ic);
960 //              pic16_emitpcomment("ic: %s\n", iLine);
961 //              dbuf_free(iLine);
962
963                 if (ic->op == '+') {
964                         val += (int) operandLitValue(IC_RIGHT(ic));
965                 } else if (ic->op == '-') {
966                         val -= (int) operandLitValue(IC_RIGHT(ic));
967                 } else
968                         break;
969
970                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
971         }
972
973         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
974         refop = IC_LEFT(ic);
975
976         if(!op->isaddr)viaimmd++; else viaimmd=0;
977
978 /* set the following if to 1 to revert to good old immediate code */
979         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
980                 || viaimmd) {
981
982                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
983
984                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
985
986 #if 0
987                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
988 #else
989                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
990 #endif
991
992                 PCOI(aop->aopu.pcop)->index = val;
993
994                 aop->size = getSize( sym->type );
995         } else {
996                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
997
998                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
999                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
1000
1001                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
1002         }
1003
1004
1005         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1006                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1007 #if 0
1008                 val, IS_PTR_CONST(operandType(op)));
1009 #else
1010                 val, IS_CODEPTR(operandType(op)));
1011 #endif
1012
1013 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1014
1015         pic16_allocDirReg (IC_LEFT(ic));
1016
1017         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1018                 aop->code = 1;
1019
1020   return aop;
1021 }
1022
1023 #if 0
1024 static int aopIdx (asmop *aop, int offset)
1025 {
1026   if(!aop)
1027     return -1;
1028
1029   if(aop->type !=  AOP_REG)
1030     return -2;
1031
1032   return aop->aopu.aop_reg[offset]->rIdx;
1033
1034 }
1035 #endif
1036
1037 /*-----------------------------------------------------------------*/
1038 /* regsInCommon - two operands have some registers in common       */
1039 /*-----------------------------------------------------------------*/
1040 static bool regsInCommon (operand *op1, operand *op2)
1041 {
1042     symbol *sym1, *sym2;
1043     int i;
1044
1045     /* if they have registers in common */
1046     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1047         return FALSE ;
1048
1049     sym1 = OP_SYMBOL(op1);
1050     sym2 = OP_SYMBOL(op2);
1051
1052     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1053         return FALSE ;
1054
1055     for (i = 0 ; i < sym1->nRegs ; i++) {
1056         int j;
1057         if (!sym1->regs[i])
1058             continue ;
1059
1060         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1061             if (!sym2->regs[j])
1062                 continue ;
1063
1064             if (sym2->regs[j] == sym1->regs[i])
1065                 return TRUE ;
1066         }
1067     }
1068
1069     return FALSE ;
1070 }
1071
1072 /*-----------------------------------------------------------------*/
1073 /* operandsEqu - equivalent                                        */
1074 /*-----------------------------------------------------------------*/
1075 static bool operandsEqu ( operand *op1, operand *op2)
1076 {
1077     symbol *sym1, *sym2;
1078
1079     /* if they not symbols */
1080     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1081         return FALSE;
1082
1083     sym1 = OP_SYMBOL(op1);
1084     sym2 = OP_SYMBOL(op2);
1085
1086     /* if both are itemps & one is spilt
1087        and the other is not then false */
1088     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1089         sym1->isspilt != sym2->isspilt )
1090         return FALSE ;
1091
1092     /* if they are the same */
1093     if (sym1 == sym2)
1094         return TRUE ;
1095
1096     if (sym1->rname[0] && sym2->rname[0]
1097         && strcmp (sym1->rname, sym2->rname) == 0)
1098         return TRUE;
1099
1100
1101     /* if left is a tmp & right is not */
1102     if (IS_ITEMP(op1)  &&
1103         !IS_ITEMP(op2) &&
1104         sym1->isspilt  &&
1105         (sym1->usl.spillLoc == sym2))
1106         return TRUE;
1107
1108     if (IS_ITEMP(op2)  &&
1109         !IS_ITEMP(op1) &&
1110         sym2->isspilt  &&
1111         sym1->level > 0 &&
1112         (sym2->usl.spillLoc == sym1))
1113         return TRUE ;
1114
1115     return FALSE ;
1116 }
1117
1118 /*-----------------------------------------------------------------*/
1119 /* pic16_sameRegs - two asmops have the same registers                   */
1120 /*-----------------------------------------------------------------*/
1121 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1122 {
1123     int i;
1124
1125     if (aop1 == aop2)
1126         return TRUE ;
1127
1128     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1129                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1130
1131     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1132
1133     if (aop1->type != AOP_REG ||
1134         aop2->type != AOP_REG )
1135         return FALSE ;
1136
1137     /* This is a bit too restrictive if one is a subset of the other...
1138     if (aop1->size != aop2->size )
1139         return FALSE ;
1140     */
1141
1142     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1143 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1144
1145 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1146         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1147             return FALSE ;
1148     }
1149
1150     return TRUE ;
1151 }
1152
1153 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1154 {
1155     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1156                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1157
1158     if(aop1 == aop2)return TRUE;
1159     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1160
1161       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1162
1163   return TRUE;
1164 }
1165
1166
1167 /*-----------------------------------------------------------------*/
1168 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1169 /*-----------------------------------------------------------------*/
1170 void pic16_aopOp (operand *op, iCode *ic, bool result)
1171 {
1172     asmop *aop;
1173     symbol *sym;
1174     int i;
1175
1176     if (!op)
1177         return ;
1178
1179     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1180
1181     /* if this a literal */
1182     if (IS_OP_LITERAL(op)) {
1183         op->aop = aop = newAsmop(AOP_LIT);
1184         aop->aopu.aop_lit = op->operand.valOperand;
1185         aop->size = getSize(operandType(op));
1186         return;
1187     }
1188
1189     {
1190       sym_link *type = operandType(op);
1191 #if 0
1192       if(IS_PTR_CONST(type))
1193 #else
1194       if(IS_CODEPTR(type))
1195 #endif
1196         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1197     }
1198
1199     /* if already has a asmop then continue */
1200     if (op->aop)
1201         return ;
1202
1203     /* if the underlying symbol has a aop */
1204     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1205       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1206         op->aop = OP_SYMBOL(op)->aop;
1207         return;
1208     }
1209
1210     /* if this is a true symbol */
1211     if (IS_TRUE_SYMOP(op)) {
1212         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1213       op->aop = aopForSym(ic, op, result);
1214       return ;
1215     }
1216
1217     /* this is a temporary : this has
1218     only four choices :
1219     a) register
1220     b) spillocation
1221     c) rematerialize
1222     d) conditional
1223     e) can be a return use only */
1224
1225     sym = OP_SYMBOL(op);
1226
1227     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1228     /* if the type is a conditional */
1229     if (sym->regType == REG_CND) {
1230         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1231         aop->size = 0;
1232         return;
1233     }
1234
1235     /* if it is spilt then two situations
1236     a) is rematerialize
1237     b) has a spill location */
1238     if (sym->isspilt || sym->nRegs == 0) {
1239
1240 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1241       DEBUGpic16_emitcode(";","%d",__LINE__);
1242         /* rematerialize it NOW */
1243         if (sym->remat) {
1244
1245             sym->aop = op->aop = aop = aopForRemat (op, result);
1246 //            aop->size = getSize(sym->type);
1247 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1248             return;
1249         }
1250
1251 #if 1
1252         if (sym->accuse) {
1253             int i;
1254             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1255             aop->size = getSize(sym->type);
1256             for ( i = 0 ; i < 1 ; i++ ) {
1257                 aop->aopu.aop_str[i] = accUse[i];
1258 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1259             }
1260             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1261             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1262             return;
1263         }
1264 #endif
1265
1266 #if 1
1267         if (sym->ruonly) {
1268           /*
1269           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1270           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1271           //pic16_allocDirReg (IC_LEFT(ic));
1272           aop->size = getSize(sym->type);
1273           */
1274
1275           unsigned i;
1276
1277           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1278           aop->size = getSize(sym->type);
1279           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1280             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1281
1282           DEBUGpic16_emitcode(";","%d",__LINE__);
1283           return;
1284         }
1285 #endif
1286         /* else spill location  */
1287         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1288             /* force a new aop if sizes differ */
1289             sym->usl.spillLoc->aop = NULL;
1290         }
1291
1292 #if 0
1293         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1294                             __FUNCTION__,__LINE__,
1295                             sym->usl.spillLoc->rname,
1296                             sym->rname, sym->usl.spillLoc->offset);
1297 #endif
1298
1299         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1300         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1301           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1303                                                   getSize(sym->type),
1304                                                   sym->usl.spillLoc->offset, op);
1305         } else if (getSize(sym->type) <= 1) {
1306           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1307           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1308           assert (getSize(sym->type) <= 1);
1309           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1310           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1311         } else {
1312           /* We need some kind of dummy area for getSize(sym->type) byte,
1313            * use WREG for all storage locations.
1314            * XXX: This only works if we are implementing a `dummy read',
1315            *      the stored value will not be retrievable...
1316            *      See #1503234 for a case requiring this. */
1317           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1318           aop->size = getSize(sym->type);
1319           for ( i = 0 ; i < aop->size ;i++)
1320             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1321         }
1322         aop->size = getSize(sym->type);
1323
1324         return;
1325     }
1326
1327     {
1328       sym_link *type = operandType(op);
1329 #if 0
1330       if(IS_PTR_CONST(type))
1331 #else
1332       if(IS_CODEPTR(type))
1333 #endif
1334         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1335     }
1336
1337     /* must be in a register */
1338     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1339     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1340     aop->size = sym->nRegs;
1341     for ( i = 0 ; i < sym->nRegs ;i++)
1342         aop->aopu.aop_reg[i] = sym->regs[i];
1343 }
1344
1345 /*-----------------------------------------------------------------*/
1346 /* pic16_freeAsmop - free up the asmop given to an operand               */
1347 /*----------------------------------------------------------------*/
1348 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1349 {
1350     asmop *aop ;
1351
1352     if (!op)
1353         aop = aaop;
1354     else
1355         aop = op->aop;
1356
1357     if (!aop)
1358         return ;
1359
1360     if (aop->freed)
1361         goto dealloc;
1362
1363     aop->freed = 1;
1364
1365     /* depending on the asmop type only three cases need work AOP_RO
1366        , AOP_R1 && AOP_STK */
1367 #if 1
1368     switch (aop->type) {
1369         case AOP_FSR0 :
1370             if (_G.fsr0Pushed ) {
1371                 if (pop) {
1372                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1373                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1374 //                    pic16_emitcode ("pop","ar0");
1375                     _G.fsr0Pushed--;
1376                 }
1377             }
1378             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1379             break;
1380
1381         case AOP_FSR2 :
1382             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1383             break;
1384
1385         case AOP_R0 :
1386             if (_G.r0Pushed ) {
1387                 if (pop) {
1388                     pic16_emitcode ("pop","ar0");
1389                     _G.r0Pushed--;
1390                 }
1391             }
1392             bitVectUnSetBit(ic->rUsed,R0_IDX);
1393             break;
1394
1395         case AOP_R1 :
1396             if (_G.r1Pushed ) {
1397                 if (pop) {
1398                     pic16_emitcode ("pop","ar1");
1399                     _G.r1Pushed--;
1400                 }
1401             }
1402             bitVectUnSetBit(ic->rUsed,R1_IDX);
1403             break;
1404
1405         case AOP_STA:
1406           {
1407             int i;
1408
1409               /* we must store the result on stack */
1410               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1411                 // operands on stack are accessible via "FSR2 + index" with index
1412                 // starting at 2 for arguments and growing from 0 downwards for
1413                 // local variables (index == 0 is not assigned so we add one here)
1414                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1415                 if (soffs <= 0) {
1416                   assert (soffs < 0);
1417                   soffs++;
1418                 } // if
1419                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1420                 for(i=0;i<aop->size;i++) {
1421                   /* initialise for stack access via frame pointer */
1422                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1423                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1424                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1425                 }
1426
1427                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1428               }
1429
1430               if(!_G.resDirect) {
1431                 for(i=0;i<aop->size;i++) {
1432                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1433
1434                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1435                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1436 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1437                   }
1438                 }
1439
1440                 {
1441                   regs *sr;
1442
1443                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1444                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1445                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1446                       deleteSetItem( &_G.sregsAllocSet, sr );
1447                     }
1448                 }
1449               }
1450               _G.resDirect = 0;
1451           }
1452           break;
1453 #if 0
1454         case AOP_STK :
1455         {
1456             int sz = aop->size;
1457             int stk = aop->aopu.aop_stk + aop->size;
1458             bitVectUnSetBit(ic->rUsed,R0_IDX);
1459             bitVectUnSetBit(ic->rUsed,R1_IDX);
1460
1461             getFreePtr(ic,&aop,FALSE);
1462
1463             if (options.stack10bit)
1464             {
1465                 /* I'm not sure what to do here yet... */
1466                 /* #STUB */
1467                 fprintf(stderr,
1468                         "*** Warning: probably generating bad code for "
1469                         "10 bit stack mode.\n");
1470             }
1471
1472             if (stk) {
1473                 pic16_emitcode ("mov","a,_bp");
1474                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1475                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1476             } else {
1477                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1478             }
1479
1480             while (sz--) {
1481                 pic16_emitcode("pop","acc");
1482                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1483                 if (!sz) break;
1484                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1485             }
1486             op->aop = aop;
1487             pic16_freeAsmop(op,NULL,ic,TRUE);
1488             if (_G.r0Pushed) {
1489                 pic16_emitcode("pop","ar0");
1490                 _G.r0Pushed--;
1491             }
1492
1493             if (_G.r1Pushed) {
1494                 pic16_emitcode("pop","ar1");
1495                 _G.r1Pushed--;
1496             }
1497         }
1498 #endif
1499
1500     }
1501 #endif
1502
1503 dealloc:
1504     /* all other cases just dealloc */
1505     if (op ) {
1506         op->aop = NULL;
1507         if (IS_SYMOP(op)) {
1508             OP_SYMBOL(op)->aop = NULL;
1509             /* if the symbol has a spill */
1510             if (SPIL_LOC(op))
1511                 SPIL_LOC(op)->aop = NULL;
1512         }
1513     }
1514 }
1515
1516 /*-----------------------------------------------------------------*/
1517 /* pic16_aopGet - for fetching value of the aop                          */
1518 /*-----------------------------------------------------------------*/
1519 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1520 {
1521     char *s = buffer ;
1522     char *rs;
1523
1524     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1525
1526     /* offset is greater than size then zero */
1527     if (offset > (aop->size - 1) &&
1528         aop->type != AOP_LIT)
1529         return zero;
1530
1531     /* depending on type */
1532     switch (aop->type) {
1533
1534     case AOP_FSR0:
1535     case AOP_FSR2:
1536       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1537       rs = Safe_calloc(1, strlen(s)+1);
1538       strcpy(rs, s);
1539       return (rs);
1540
1541 #if 0
1542       /* if we need to increment it */
1543       while (offset > aop->coff)
1544         {
1545           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1546           aop->coff++;
1547         }
1548
1549       while (offset < aop->coff)
1550         {
1551           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1552           aop->coff--;
1553         }
1554       aop->coff = offset;
1555       if (aop->paged)
1556         {
1557           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1558           return (dname ? "acc" : "a");
1559         }
1560       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1561       rs = Safe_calloc (1, strlen (s) + 1);
1562       strcpy (rs, s);
1563       return rs;
1564 #endif
1565
1566
1567     case AOP_IMMD:
1568         if (bit16)
1569             sprintf (s,"%s",aop->aopu.aop_immd);
1570         else
1571             if (offset)
1572                 sprintf(s,"(%s >> %d)",
1573                         aop->aopu.aop_immd,
1574                         offset*8);
1575             else
1576                 sprintf(s,"%s",
1577                         aop->aopu.aop_immd);
1578         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1579         rs = Safe_calloc(1,strlen(s)+1);
1580         strcpy(rs,s);
1581         return rs;
1582
1583     case AOP_DIR:
1584       if (offset) {
1585         sprintf(s,"(%s + %d)",
1586                 aop->aopu.aop_dir,
1587                 offset);
1588         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1589       } else
1590             sprintf(s,"%s",aop->aopu.aop_dir);
1591         rs = Safe_calloc(1,strlen(s)+1);
1592         strcpy(rs,s);
1593         return rs;
1594
1595     case AOP_REG:
1596       return aop->aopu.aop_reg[offset]->name;
1597
1598     case AOP_CRY:
1599       return aop->aopu.aop_dir;
1600
1601     case AOP_ACC:
1602         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1603 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1604 //        assert( 0 );
1605 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1606         rs = Safe_strdup("WREG");
1607         return (rs);
1608
1609     case AOP_LIT:
1610         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1611         rs = Safe_calloc(1,strlen(s)+1);
1612         strcpy(rs,s);
1613         return rs;
1614
1615     case AOP_STR:
1616         aop->coff = offset ;
1617
1618 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1619 //          dname)
1620 //          return "acc";
1621         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1622           aop->type = AOP_ACC;
1623           return Safe_strdup("_WREG");
1624         }
1625         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1626
1627         return aop->aopu.aop_str[offset];
1628
1629     case AOP_PCODE:
1630       {
1631         pCodeOp *pcop = aop->aopu.pcop;
1632         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1633         if(pcop->name) {
1634           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1635           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1636           if (offset) {
1637             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1638           } else {
1639             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1640           }
1641         } else
1642           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1643
1644       }
1645       rs = Safe_calloc(1,strlen(s)+1);
1646       strcpy(rs,s);
1647       return rs;
1648
1649 #if 0
1650     case AOP_PAGED:
1651       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1652       if (offset) {
1653         sprintf(s,"(%s + %d)",
1654                 aop->aopu.aop_dir,
1655                 offset);
1656       } else
1657             sprintf(s,"%s",aop->aopu.aop_dir);
1658       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1659       rs = Safe_calloc(1,strlen(s)+1);
1660       strcpy(rs,s);
1661       return rs;
1662 #endif
1663
1664     case AOP_STA:
1665         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1666         return (rs);
1667
1668     case AOP_STK:
1669 //        pCodeOp *pcop = aop->aop
1670         break;
1671
1672     }
1673
1674     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1675     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1676            "aopget got unsupported aop->type");
1677     exit(0);
1678 }
1679
1680
1681
1682 /* lock has the following meaning: When allocating temporary registers
1683  * for stack variables storage, the value of the temporary register is
1684  * saved on stack. Its value is restored at the end. This procedure is
1685  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1686  * a possibility that before a call to pic16_aopOp, a temporary register
1687  * is allocated for a while and it is freed after some time, this will
1688  * mess the stack and values will not be restored properly. So use lock=1
1689  * to allocate temporary registers used internally by the programmer, and
1690  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1691  * to inform the compiler developer about a possible bug. This is an internal
1692  * feature for developing the compiler -- VR */
1693
1694 int _TempReg_lock = 0;
1695 /*-----------------------------------------------------------------*/
1696 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1697 /*-----------------------------------------------------------------*/
1698 pCodeOp *pic16_popGetTempReg(int lock)
1699 {
1700   pCodeOp *pcop=NULL;
1701   symbol *cfunc;
1702
1703 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1704     if(_TempReg_lock) {
1705 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1706     }
1707
1708     _TempReg_lock += lock;
1709
1710     cfunc = currFunc;
1711     currFunc = NULL;
1712
1713 #if 0
1714         {
1715           regs *rr;
1716           int i;
1717
1718                 /* this code might seem better but it does the *same* job with
1719                  * the old code, it all depends on ralloc.c to get a free/unused
1720                  * register */
1721
1722                 i=0;
1723                 while(i < pic16_nRegs) {
1724                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1725                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1726                         if((!rr || (rr && rr->isFree))
1727                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1728                                 pcop = pic16_newpCodeOpReg( i );
1729                                 PCOR(pcop)->r->wasUsed = 1;
1730                                 PCOR(pcop)->r->isFree = 0;
1731                                 break;
1732                         }
1733                         i++;
1734                 }
1735
1736                 if(pcop) {
1737                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1738                 }
1739         }
1740 #else
1741     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1742     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1743       PCOR(pcop)->r->wasUsed=1;
1744       PCOR(pcop)->r->isFree=0;
1745
1746       /* push value on stack */
1747       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1748     }
1749 #endif
1750
1751     currFunc = cfunc;
1752
1753   return pcop;
1754 }
1755
1756 /*-----------------------------------------------------------------*/
1757 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1758 /*                           is not part of f, but don't save if   */
1759 /*                           inside v                              */
1760 /*-----------------------------------------------------------------*/
1761 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1762 {
1763   pCodeOp *pcop=NULL;
1764   symbol *cfunc;
1765   int i;
1766
1767 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1768
1769     if(_TempReg_lock) {
1770 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1771     }
1772
1773     _TempReg_lock += lock;
1774
1775     cfunc = currFunc;
1776     currFunc = NULL;
1777
1778     i = bitVectFirstBit(f);
1779     while(i < 128) {
1780
1781       /* bypass registers that are used by function */
1782       if(!bitVectBitValue(f, i)) {
1783
1784         /* bypass registers that are already allocated for stack access */
1785         if(!bitVectBitValue(v, i))  {
1786
1787 //          debugf("getting register rIdx = %d\n", i);
1788           /* ok, get the operand */
1789           pcop = pic16_newpCodeOpReg( i );
1790
1791           /* should never by NULL */
1792           assert( pcop != NULL );
1793
1794
1795           /* sanity check */
1796           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1797             int found=0;
1798
1799               PCOR(pcop)->r->wasUsed=1;
1800               PCOR(pcop)->r->isFree=0;
1801
1802
1803               {
1804                 regs *sr;
1805
1806                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1807
1808                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1809                       /* already used in previous steps, break */
1810                       found=1;
1811                       break;
1812                     }
1813                   }
1814               }
1815
1816               /* caller takes care of the following */
1817 //              bitVectSetBit(v, i);
1818
1819               if(!found) {
1820                 /* push value on stack */
1821                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1822                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1823               }
1824
1825             break;
1826           }
1827         }
1828       }
1829       i++;
1830     }
1831
1832     currFunc = cfunc;
1833
1834   return pcop;
1835 }
1836
1837
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1840 /*-----------------------------------------------------------------*/
1841 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1842 {
1843   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1844
1845   _TempReg_lock -= lock;
1846
1847   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1848     PCOR(pcop)->r->isFree = 1;
1849
1850     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1851   }
1852 }
1853 /*-----------------------------------------------------------------*/
1854 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1855 /*-----------------------------------------------------------------*/
1856 pCodeOp *pic16_popGetLabel(int key)
1857 {
1858
1859   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1860
1861   if(key>max_key)
1862     max_key = key;
1863
1864   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1865 }
1866
1867 /*-----------------------------------------------------------------*/
1868 /* pic16_popCopyReg - copy a pcode operator                              */
1869 /*-----------------------------------------------------------------*/
1870 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1871 {
1872   pCodeOpReg *pcor;
1873
1874   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1875   memcpy (pcor, pc, sizeof (pCodeOpReg));
1876   pcor->r->wasUsed = 1;
1877
1878   //pcor->pcop.type = pc->pcop.type;
1879   if(pc->pcop.name) {
1880     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1881       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1882   } else
1883     pcor->pcop.name = NULL;
1884
1885   //pcor->r = pc->r;
1886   //pcor->rIdx = pc->rIdx;
1887   //pcor->r->wasUsed=1;
1888   //pcor->instance = pc->instance;
1889
1890 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1891
1892   return PCOP(pcor);
1893 }
1894
1895 /*-----------------------------------------------------------------*/
1896 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1897 /*-----------------------------------------------------------------*/
1898 pCodeOp *pic16_popGetLit(int lit)
1899 {
1900   return pic16_newpCodeOpLit(lit);
1901 }
1902
1903 /* Allow for 12 bit literals (LFSR x, <here!>). */
1904 pCodeOp *pic16_popGetLit12(int lit)
1905 {
1906   return pic16_newpCodeOpLit12(lit);
1907 }
1908
1909 /*-----------------------------------------------------------------*/
1910 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1911 /*-----------------------------------------------------------------*/
1912 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1913 {
1914   return pic16_newpCodeOpLit2(lit, arg2);
1915 }
1916
1917
1918 /*-----------------------------------------------------------------*/
1919 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1920 /*-----------------------------------------------------------------*/
1921 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1922 {
1923   return pic16_newpCodeOpImmd(name, offset,index, 0);
1924 }
1925
1926
1927 /*-----------------------------------------------------------------*/
1928 /* pic16_popGet - asm operator to pcode operator conversion              */
1929 /*-----------------------------------------------------------------*/
1930 pCodeOp *pic16_popGetWithString(char *str)
1931 {
1932   pCodeOp *pcop;
1933
1934
1935   if(!str) {
1936     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1937     exit (1);
1938   }
1939
1940   pcop = pic16_newpCodeOp(str,PO_STR);
1941
1942   return pcop;
1943 }
1944
1945 /*-----------------------------------------------------------------*/
1946 /* pic16_popRegFromString -                                        */
1947 /*-----------------------------------------------------------------*/
1948 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1949 {
1950
1951   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1952   pcop->type = PO_DIR;
1953
1954   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1955   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1956
1957   if(!str)
1958     str = "BAD_STRING";
1959
1960   pcop->name = Safe_calloc(1,strlen(str)+1);
1961   strcpy(pcop->name,str);
1962
1963   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1964
1965   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1966 //  PCOR(pcop)->r->wasUsed = 1;
1967
1968   /* make sure that register doesn't exist,
1969    * and operand isn't NULL
1970    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1971   if((PCOR(pcop)->r == NULL)
1972     && (op)
1973     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1974 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1975 //              __FUNCTION__, __LINE__, str, size, offset);
1976
1977     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1978     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1979
1980   }
1981   PCOR(pcop)->instance = offset;
1982
1983   return pcop;
1984 }
1985
1986 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1987 {
1988   pCodeOp *pcop;
1989
1990 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1991 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1992
1993         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1994         PCOR(pcop)->rIdx = rIdx;
1995         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1996         if(!PCOR(pcop)->r)
1997                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1998
1999         PCOR(pcop)->r->isFree = 0;
2000         PCOR(pcop)->r->wasUsed = 1;
2001
2002         pcop->type = PCOR(pcop)->r->pc_type;
2003
2004   return pcop;
2005 }
2006
2007 /*---------------------------------------------------------------------------------*/
2008 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2009 /*                 VR 030601                                                       */
2010 /*---------------------------------------------------------------------------------*/
2011 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2012 {
2013   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2014         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2015   return PCOP(pcop2);
2016 }
2017
2018
2019
2020 /*--------------------------------------------------------------------------------.-*/
2021 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2022 /*                  VR 030601 , adapted by Hans Dorn                                */
2023 /*--------------------------------------------------------------------------------.-*/
2024 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2025 {
2026   pCodeOp2 *pcop2;
2027   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2028   return PCOP(pcop2);
2029 }
2030
2031 /*---------------------------------------------------------------------------------*/
2032 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2033 /*                     movff instruction                                           */
2034 /*---------------------------------------------------------------------------------*/
2035 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2036 {
2037   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2038         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2039
2040   return PCOP(pcop2);
2041 }
2042
2043
2044 /*-----------------------------------------------------------------*/
2045 /* pic16_popGet - asm operator to pcode operator conversion              */
2046 /*-----------------------------------------------------------------*/
2047 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2048 {
2049 //  char *s = buffer ;
2050 //  char *rs;
2051   pCodeOp *pcop;
2052
2053     FENTRY2;
2054
2055       /* offset is greater than size then zero */
2056
2057 //    if (offset > (aop->size - 1) &&
2058 //        aop->type != AOP_LIT)
2059 //      return NULL;  //zero;
2060
2061     /* depending on type */
2062     switch (aop->type) {
2063                 case AOP_R0:
2064                 case AOP_R1:
2065                 case AOP_DPTR:
2066                 case AOP_DPTR2:
2067                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2068                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2069                         assert( 0 );
2070                         return NULL;
2071
2072                 case AOP_FSR0:
2073                 case AOP_FSR2:
2074                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2075                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2076                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2077                         PCOR(pcop)->r->wasUsed = 1;
2078                         PCOR(pcop)->r->isFree = 0;
2079
2080                         PCOR(pcop)->instance = offset;
2081                         pcop->type = PCOR(pcop)->r->pc_type;
2082                         return (pcop);
2083
2084                 case AOP_IMMD:
2085                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2086                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2087
2088                 case AOP_STA:
2089                         /* pCodeOp is already allocated from aopForSym */
2090                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2091                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2092                         return (pcop);
2093
2094                 case AOP_ACC:
2095                         {
2096                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2097
2098                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2099
2100                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2101
2102                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2103                                 PCOR(pcop)->rIdx = rIdx;
2104                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2105                                 PCOR(pcop)->r->wasUsed=1;
2106                                 PCOR(pcop)->r->isFree=0;
2107
2108                                 PCOR(pcop)->instance = offset;
2109                                 pcop->type = PCOR(pcop)->r->pc_type;
2110 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2111                                 return pcop;
2112
2113
2114 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2115 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2116
2117 //      assert( 0 );
2118                         }
2119
2120     case AOP_DIR:
2121       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2122       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2123
2124 #if 0
2125     case AOP_PAGED:
2126       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2127       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2128 #endif
2129
2130     case AOP_REG:
2131       {
2132         int rIdx;
2133
2134 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2135 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2136         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2137
2138         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2139
2140         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2141 //      pcop->type = PO_GPR_REGISTER;
2142         PCOR(pcop)->rIdx = rIdx;
2143         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2144         PCOR(pcop)->r->wasUsed=1;
2145         PCOR(pcop)->r->isFree=0;
2146
2147         PCOR(pcop)->instance = offset;
2148         pcop->type = PCOR(pcop)->r->pc_type;
2149
2150         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2151 //      rs = aop->aopu.aop_reg[offset]->name;
2152 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2153         return pcop;
2154       }
2155
2156     case AOP_CRY:
2157         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2158
2159       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2160       PCOR(pcop)->instance = offset;
2161       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2162       //if(PCOR(pcop)->r == NULL)
2163       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2164       return pcop;
2165
2166     case AOP_LIT:
2167         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2168       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2169
2170     case AOP_STR:
2171       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2172       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2173
2174       /*
2175       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2176       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2177       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2178       pcop->type = PCOR(pcop)->r->pc_type;
2179       pcop->name = PCOR(pcop)->r->name;
2180
2181       return pcop;
2182       */
2183
2184     case AOP_PCODE:
2185       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2186                           __LINE__,
2187                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2188       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2189       switch( aop->aopu.pcop->type ) {
2190         case PO_DIR: PCOR(pcop)->instance += offset; break;
2191         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2192         case PO_WREG:
2193             assert (offset==0);
2194             break;
2195         default:
2196           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2197           assert( 0 );  /* should never reach here */;
2198       }
2199       return pcop;
2200     }
2201
2202     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2203            "pic16_popGet got unsupported aop->type");
2204     exit(0);
2205 }
2206 /*-----------------------------------------------------------------*/
2207 /* pic16_aopPut - puts a string for a aop                                */
2208 /*-----------------------------------------------------------------*/
2209 void pic16_aopPut (asmop *aop, char *s, int offset)
2210 {
2211     char *d = buffer ;
2212     symbol *lbl ;
2213
2214     return;
2215
2216     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2217
2218     if (aop->size && offset > ( aop->size - 1)) {
2219         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2220                "pic16_aopPut got offset > aop->size");
2221         exit(0);
2222     }
2223
2224     /* will assign value to value */
2225     /* depending on where it is ofcourse */
2226     switch (aop->type) {
2227     case AOP_DIR:
2228       if (offset) {
2229         sprintf(d,"(%s + %d)",
2230                 aop->aopu.aop_dir,offset);
2231         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2232
2233       } else
2234             sprintf(d,"%s",aop->aopu.aop_dir);
2235
2236         if (strcmp(d,s)) {
2237           DEBUGpic16_emitcode(";","%d",__LINE__);
2238           if(strcmp(s,"W"))
2239             pic16_emitcode("movf","%s,w",s);
2240           pic16_emitcode("movwf","%s",d);
2241
2242           if(strcmp(s,"W")) {
2243             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2244             if(offset >= aop->size) {
2245               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2246               break;
2247             } else
2248               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2249           }
2250
2251           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2252
2253
2254         }
2255         break;
2256
2257     case AOP_REG:
2258       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2259         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2260           /*
2261             if (*s == '@'           ||
2262                 strcmp(s,"r0") == 0 ||
2263                 strcmp(s,"r1") == 0 ||
2264                 strcmp(s,"r2") == 0 ||
2265                 strcmp(s,"r3") == 0 ||
2266                 strcmp(s,"r4") == 0 ||
2267                 strcmp(s,"r5") == 0 ||
2268                 strcmp(s,"r6") == 0 ||
2269                 strcmp(s,"r7") == 0 )
2270                 pic16_emitcode("mov","%s,%s  ; %d",
2271                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2272             else
2273           */
2274
2275           if(strcmp(s,"W")==0 )
2276             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2277
2278           pic16_emitcode("movwf","%s",
2279                    aop->aopu.aop_reg[offset]->name);
2280
2281           if(strcmp(s,zero)==0) {
2282             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2283
2284           } else if(strcmp(s,"W")==0) {
2285             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2286             pcop->type = PO_GPR_REGISTER;
2287
2288             PCOR(pcop)->rIdx = -1;
2289             PCOR(pcop)->r = NULL;
2290
2291             DEBUGpic16_emitcode(";","%d",__LINE__);
2292             pcop->name = Safe_strdup(s);
2293             pic16_emitpcode(POC_MOVFW,pcop);
2294             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2295           } else if(strcmp(s,one)==0) {
2296             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2297             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2298           } else {
2299             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2300           }
2301         }
2302         break;
2303
2304     case AOP_DPTR:
2305     case AOP_DPTR2:
2306
2307     if (aop->type == AOP_DPTR2)
2308     {
2309         genSetDPTR(1);
2310     }
2311
2312         if (aop->code) {
2313             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2314                    "pic16_aopPut writting to code space");
2315             exit(0);
2316         }
2317
2318         while (offset > aop->coff) {
2319             aop->coff++;
2320             pic16_emitcode ("inc","dptr");
2321         }
2322
2323         while (offset < aop->coff) {
2324             aop->coff-- ;
2325             pic16_emitcode("lcall","__decdptr");
2326         }
2327
2328         aop->coff = offset;
2329
2330         /* if not in accumulater */
2331         MOVA(s);
2332
2333         pic16_emitcode ("movx","@dptr,a");
2334
2335     if (aop->type == AOP_DPTR2)
2336     {
2337         genSetDPTR(0);
2338     }
2339         break;
2340
2341     case AOP_R0:
2342     case AOP_R1:
2343         while (offset > aop->coff) {
2344             aop->coff++;
2345             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2346         }
2347         while (offset < aop->coff) {
2348             aop->coff-- ;
2349             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2350         }
2351         aop->coff = offset;
2352
2353         if (aop->paged) {
2354             MOVA(s);
2355             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2356
2357         } else
2358             if (*s == '@') {
2359                 MOVA(s);
2360                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2361             } else
2362                 if (strcmp(s,"r0") == 0 ||
2363                     strcmp(s,"r1") == 0 ||
2364                     strcmp(s,"r2") == 0 ||
2365                     strcmp(s,"r3") == 0 ||
2366                     strcmp(s,"r4") == 0 ||
2367                     strcmp(s,"r5") == 0 ||
2368                     strcmp(s,"r6") == 0 ||
2369                     strcmp(s,"r7") == 0 ) {
2370                     char buffer[10];
2371                     sprintf(buffer,"a%s",s);
2372                     pic16_emitcode("mov","@%s,%s",
2373                              aop->aopu.aop_ptr->name,buffer);
2374                 } else
2375                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2376
2377         break;
2378
2379     case AOP_STK:
2380         if (strcmp(s,"a") == 0)
2381             pic16_emitcode("push","acc");
2382         else
2383             pic16_emitcode("push","%s",s);
2384
2385         break;
2386
2387     case AOP_CRY:
2388         /* if bit variable */
2389         if (!aop->aopu.aop_dir) {
2390             pic16_emitcode("clr","a");
2391             pic16_emitcode("rlc","a");
2392         } else {
2393             if (s == zero)
2394                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2395             else
2396                 if (s == one)
2397                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2398                 else
2399                     if (!strcmp(s,"c"))
2400                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2401                     else {
2402                         lbl = newiTempLabel(NULL);
2403
2404                         if (strcmp(s,"a")) {
2405                             MOVA(s);
2406                         }
2407                         pic16_emitcode("clr","c");
2408                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2409                         pic16_emitcode("cpl","c");
2410                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2411                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2412                     }
2413         }
2414         break;
2415
2416     case AOP_STR:
2417         aop->coff = offset;
2418         if (strcmp(aop->aopu.aop_str[offset],s))
2419             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2420         break;
2421
2422     case AOP_ACC:
2423         aop->coff = offset;
2424         if (!offset && (strcmp(s,"acc") == 0))
2425             break;
2426
2427         if (strcmp(aop->aopu.aop_str[offset],s))
2428             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2429         break;
2430
2431     default :
2432         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2433 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2434 //             "pic16_aopPut got unsupported aop->type");
2435 //      exit(0);
2436     }
2437
2438 }
2439
2440 /*-----------------------------------------------------------------*/
2441 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2442 /*-----------------------------------------------------------------*/
2443 void pic16_mov2w (asmop *aop, int offset)
2444 {
2445   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2446
2447   if(is_LitAOp(aop))
2448     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2449   else
2450     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2451 }
2452
2453 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2454 {
2455   if(is_LitAOp(src)) {
2456     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2457     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2458   } else {
2459     if(pic16_sameRegsOfs(src, dst, offset))return;
2460     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2461                       pic16_popGet(dst, offset)));
2462   }
2463 }
2464
2465 static void pic16_movLit2f(pCodeOp *pc, int lit)
2466 {
2467   if (0 == (lit & 0x00ff))
2468   {
2469     pic16_emitpcode (POC_CLRF, pc);
2470   } else if (0xff == (lit & 0x00ff))
2471   {
2472     pic16_emitpcode (POC_SETF, pc);
2473   } else {
2474     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2475     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2476   }
2477 }
2478
2479 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2480 {
2481   if(is_LitAOp(src)) {
2482     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2483     pic16_emitpcode(POC_MOVWF, dst);
2484   } else {
2485     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2486   }
2487 }
2488
2489 void pic16_testStackOverflow(void)
2490 {
2491 #define GSTACK_TEST_NAME        "_gstack_test"
2492
2493   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2494
2495   {
2496     symbol *sym;
2497
2498       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2499       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2500 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2501       checkAddSym(&externs, sym);
2502   }
2503
2504 }
2505
2506 /* push pcop into stack */
2507 void pic16_pushpCodeOp(pCodeOp *pcop)
2508 {
2509 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2510   if (pcop->type == PO_LITERAL) {
2511     pic16_emitpcode(POC_MOVLW, pcop);
2512     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2513   } else {
2514     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2515   }
2516   if(pic16_options.gstack)
2517     pic16_testStackOverflow();
2518
2519 }
2520
2521 /* pop pcop from stack */
2522 void pic16_poppCodeOp(pCodeOp *pcop)
2523 {
2524   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2525   if(pic16_options.gstack)
2526     pic16_testStackOverflow();
2527 }
2528
2529
2530 /*-----------------------------------------------------------------*/
2531 /* pushw - pushes wreg to stack                                    */
2532 /*-----------------------------------------------------------------*/
2533 void pushw(void)
2534 {
2535   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2536   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2537   if(pic16_options.gstack)
2538     pic16_testStackOverflow();
2539 }
2540
2541
2542 /*-----------------------------------------------------------------*/
2543 /* pushaop - pushes aop to stack                                   */
2544 /*-----------------------------------------------------------------*/
2545 void pushaop(asmop *aop, int offset)
2546 {
2547   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548
2549   if(_G.resDirect)return;
2550
2551   if(is_LitAOp(aop)) {
2552     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2553     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2554   } else {
2555     pic16_emitpcode(POC_MOVFF,
2556       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2557   }
2558
2559   if(pic16_options.gstack)
2560     pic16_testStackOverflow();
2561 }
2562
2563 /*-----------------------------------------------------------------*/
2564 /* popaop - pops aop from stack                                    */
2565 /*-----------------------------------------------------------------*/
2566 void popaop(asmop *aop, int offset)
2567 {
2568   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2569   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2570   if(pic16_options.gstack)
2571     pic16_testStackOverflow();
2572 }
2573
2574 void popaopidx(asmop *aop, int offset, int index)
2575 {
2576   int ofs=1;
2577
2578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2579
2580     if(STACK_MODEL_LARGE)ofs++;
2581
2582     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2583     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2584     if(pic16_options.gstack)
2585       pic16_testStackOverflow();
2586 }
2587
2588 #if !(USE_GENERIC_SIGNED_SHIFT)
2589 /*-----------------------------------------------------------------*/
2590 /* reAdjustPreg - points a register back to where it should        */
2591 /*-----------------------------------------------------------------*/
2592 static void reAdjustPreg (asmop *aop)
2593 {
2594     int size ;
2595
2596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2597     aop->coff = 0;
2598     if ((size = aop->size) <= 1)
2599         return ;
2600     size-- ;
2601     switch (aop->type) {
2602         case AOP_R0 :
2603         case AOP_R1 :
2604             while (size--)
2605                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2606             break;
2607         case AOP_DPTR :
2608         case AOP_DPTR2:
2609             if (aop->type == AOP_DPTR2)
2610             {
2611                 genSetDPTR(1);
2612             }
2613             while (size--)
2614             {
2615                 pic16_emitcode("lcall","__decdptr");
2616             }
2617
2618             if (aop->type == AOP_DPTR2)
2619             {
2620                 genSetDPTR(0);
2621             }
2622             break;
2623
2624     }
2625
2626 }
2627 #endif
2628
2629 #if 0
2630 /*-----------------------------------------------------------------*/
2631 /* opIsGptr: returns non-zero if the passed operand is             */
2632 /* a generic pointer type.                                         */
2633 /*-----------------------------------------------------------------*/
2634 static int opIsGptr(operand *op)
2635 {
2636     sym_link *type = operandType(op);
2637
2638     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2639     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2640     {
2641         return 1;
2642     }
2643     return 0;
2644 }
2645 #endif
2646
2647 /*-----------------------------------------------------------------*/
2648 /* pic16_getDataSize - get the operand data size                         */
2649 /*-----------------------------------------------------------------*/
2650 int pic16_getDataSize(operand *op)
2651 {
2652     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2653
2654
2655     return AOP_SIZE(op);
2656
2657     // tsd- in the pic port, the genptr size is 1, so this code here
2658     // fails. ( in the 8051 port, the size was 4).
2659 #if 0
2660     int size;
2661     size = AOP_SIZE(op);
2662     if (size == GPTRSIZE)
2663     {
2664         sym_link *type = operandType(op);
2665         if (IS_GENPTR(type))
2666         {
2667             /* generic pointer; arithmetic operations
2668              * should ignore the high byte (pointer type).
2669              */
2670             size--;
2671     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2672         }
2673     }
2674     return size;
2675 #endif
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outAcc - output Acc                                             */
2680 /*-----------------------------------------------------------------*/
2681 void pic16_outAcc(operand *result)
2682 {
2683   int size,offset;
2684   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2685   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2686
2687
2688   size = pic16_getDataSize(result);
2689   if(size){
2690     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2691     size--;
2692     offset = 1;
2693     /* unsigned or positive */
2694     while(size--)
2695       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2696   }
2697
2698 }
2699
2700 /*-----------------------------------------------------------------*/
2701 /* pic16_outBitC - output a bit C                                  */
2702 /*                 Move to result the value of Carry flag -- VR    */
2703 /*-----------------------------------------------------------------*/
2704 void pic16_outBitC(operand *result)
2705 {
2706   int i;
2707
2708     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2709
2710     /* if the result is bit */
2711     if (AOP_TYPE(result) == AOP_CRY) {
2712         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2713         pic16_aopPut(AOP(result),"c",0);
2714     } else {
2715
2716         i = AOP_SIZE(result);
2717         while(i--) {
2718                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2719         }
2720         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2721     }
2722 }
2723
2724 /*-----------------------------------------------------------------*/
2725 /* pic16_outBitOp - output a bit from Op                           */
2726 /*                 Move to result the value of set/clr op -- VR    */
2727 /*-----------------------------------------------------------------*/
2728 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2729 {
2730   int i;
2731
2732     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2733
2734     /* if the result is bit */
2735     if (AOP_TYPE(result) == AOP_CRY) {
2736         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2737         pic16_aopPut(AOP(result),"c",0);
2738     } else {
2739
2740         i = AOP_SIZE(result);
2741         while(i--) {
2742                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2743         }
2744         pic16_emitpcode(POC_RRCF, pcop);
2745         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2746     }
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2751 /*-----------------------------------------------------------------*/
2752 void pic16_toBoolean(operand *oper)
2753 {
2754     int size = AOP_SIZE(oper) - 1;
2755     int offset = 1;
2756
2757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2758
2759     if ( AOP_TYPE(oper) != AOP_ACC) {
2760       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2761     }
2762     while (size--) {
2763       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2764     }
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* genUminusFloat - unary minus for floating points                */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminusFloat(operand *op,operand *result)
2771 {
2772   int size ,offset =0 ;
2773
2774     FENTRY;
2775     /* for this we just need to flip the
2776     first it then copy the rest in place */
2777     size = AOP_SIZE(op);
2778     assert( size == AOP_SIZE(result) );
2779
2780     while(size--) {
2781       pic16_mov2f(AOP(result), AOP(op), offset);
2782       offset++;
2783     }
2784
2785     /* toggle the MSB's highest bit */
2786     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2787 }
2788
2789 /*-----------------------------------------------------------------*/
2790 /* genUminus - unary minus code generation                         */
2791 /*-----------------------------------------------------------------*/
2792 static void genUminus (iCode *ic)
2793 {
2794   int size, i;
2795   sym_link *optype, *rtype;
2796   symbol *label;
2797   int needLabel=0;
2798
2799     FENTRY;
2800
2801     /* assign asmops */
2802     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2803     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2804
2805     /* if both in bit space then special case */
2806     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2807       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2808
2809         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2810         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2811         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2812         goto release;
2813     }
2814
2815     optype = operandType(IC_LEFT(ic));
2816     rtype = operandType(IC_RESULT(ic));
2817
2818
2819     /* if float then do float stuff */
2820     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2821       if(IS_FIXED(optype))
2822         debugf("implement fixed16x16 type\n", 0);
2823
2824         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2825         goto release;
2826     }
2827
2828     /* otherwise subtract from zero by taking the 2's complement */
2829     size = AOP_SIZE(IC_LEFT(ic));
2830     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2831     label = newiTempLabel ( NULL );
2832
2833     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2834       for (i=size-1; i > 0; i--) {
2835         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2836       } // for
2837       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2838       for (i=1; i < size; i++) {
2839         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2840         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2841       } // for
2842     } else {
2843       for (i=size-1; i >= 0; i--) {
2844         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2845         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2846       } // for
2847       if (size > 1) {
2848         for (i=0; i < size-2; i++) {
2849           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2850           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2851         } // for
2852         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2853       } // if
2854       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2855     }
2856     if (needLabel)
2857       pic16_emitpLabel (label->key);
2858
2859 release:
2860     /* release the aops */
2861     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2862     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2863 }
2864
2865 #if 0
2866 /*-----------------------------------------------------------------*/
2867 /* saveRegisters - will look for a call and save the registers     */
2868 /*-----------------------------------------------------------------*/
2869 static void saveRegisters(iCode *lic)
2870 {
2871     int i;
2872     iCode *ic;
2873     bitVect *rsave;
2874     sym_link *dtype;
2875
2876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2877     /* look for call */
2878     for (ic = lic ; ic ; ic = ic->next)
2879         if (ic->op == CALL || ic->op == PCALL)
2880             break;
2881
2882     if (!ic) {
2883         fprintf(stderr,"found parameter push with no function call\n");
2884         return ;
2885     }
2886
2887     /* if the registers have been saved already then
2888     do nothing */
2889     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2890         return ;
2891
2892     /* find the registers in use at this time
2893     and push them away to safety */
2894     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2895                           ic->rUsed);
2896
2897     ic->regsSaved = 1;
2898     if (options.useXstack) {
2899         if (bitVectBitValue(rsave,R0_IDX))
2900             pic16_emitcode("mov","b,r0");
2901         pic16_emitcode("mov","r0,%s",spname);
2902         for (i = 0 ; i < pic16_nRegs ; i++) {
2903             if (bitVectBitValue(rsave,i)) {
2904                 if (i == R0_IDX)
2905                     pic16_emitcode("mov","a,b");
2906                 else
2907                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2908                 pic16_emitcode("movx","@r0,a");
2909                 pic16_emitcode("inc","r0");
2910             }
2911         }
2912         pic16_emitcode("mov","%s,r0",spname);
2913         if (bitVectBitValue(rsave,R0_IDX))
2914             pic16_emitcode("mov","r0,b");
2915     }// else
2916     //for (i = 0 ; i < pic16_nRegs ; i++) {
2917     //    if (bitVectBitValue(rsave,i))
2918     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2919     //}
2920
2921     dtype = operandType(IC_LEFT(ic));
2922     if (currFunc && dtype &&
2923         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2924         IFFUNC_ISISR(currFunc->type) &&
2925         !ic->bankSaved)
2926
2927         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2928
2929 }
2930 /*-----------------------------------------------------------------*/
2931 /* unsaveRegisters - pop the pushed registers                      */
2932 /*-----------------------------------------------------------------*/
2933 static void unsaveRegisters (iCode *ic)
2934 {
2935     int i;
2936     bitVect *rsave;
2937
2938     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2939     /* find the registers in use at this time
2940     and push them away to safety */
2941     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2942                           ic->rUsed);
2943
2944     if (options.useXstack) {
2945         pic16_emitcode("mov","r0,%s",spname);
2946         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2947             if (bitVectBitValue(rsave,i)) {
2948                 pic16_emitcode("dec","r0");
2949                 pic16_emitcode("movx","a,@r0");
2950                 if (i == R0_IDX)
2951                     pic16_emitcode("mov","b,a");
2952                 else
2953                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2954             }
2955
2956         }
2957         pic16_emitcode("mov","%s,r0",spname);
2958         if (bitVectBitValue(rsave,R0_IDX))
2959             pic16_emitcode("mov","r0,b");
2960     } //else
2961     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2962     //    if (bitVectBitValue(rsave,i))
2963     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2964     //}
2965
2966 }
2967 #endif
2968
2969 #if 0  // patch 14
2970 /*-----------------------------------------------------------------*/
2971 /* pushSide -                                                      */
2972 /*-----------------------------------------------------------------*/
2973 static void pushSide(operand * oper, int size)
2974 {
2975         int offset = 0;
2976     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2977         while (size--) {
2978                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2979                 if (AOP_TYPE(oper) != AOP_REG &&
2980                     AOP_TYPE(oper) != AOP_DIR &&
2981                     strcmp(l,"a") ) {
2982                         pic16_emitcode("mov","a,%s",l);
2983                         pic16_emitcode("push","acc");
2984                 } else
2985                         pic16_emitcode("push","%s",l);
2986         }
2987 }
2988 #endif // patch 14
2989
2990 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2991 {
2992   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2993     pic16_emitpcode(POC_MOVFW, src);
2994     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2995   } else {
2996     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2997         src, pic16_popGet(AOP(op), offset)));
2998   }
2999 }
3000
3001
3002 /*-----------------------------------------------------------------*/
3003 /* assignResultValue - assign results to oper, rescall==1 is       */
3004 /*                     called from genCall() or genPcall()         */
3005 /*-----------------------------------------------------------------*/
3006 static void assignResultValue(operand * oper, int res_size, int rescall)
3007 {
3008   int size = AOP_SIZE(oper);
3009   int offset=0;
3010
3011     FENTRY2;
3012 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3013     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3014
3015     if(rescall) {
3016       /* assign result from a call/pcall function() */
3017
3018       /* function results are stored in a special order,
3019        * see top of file with Function return policy, or manual */
3020
3021       if(size <= 4) {
3022         /* 8-bits, result in WREG */
3023         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3024
3025         if(size > 1 && res_size > 1) {
3026           /* 16-bits, result in PRODL:WREG */
3027           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3028         }
3029
3030         if(size > 2 && res_size > 2) {
3031           /* 24-bits, result in PRODH:PRODL:WREG */
3032           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3033         }
3034
3035         if(size > 3 && res_size > 3) {
3036           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3037           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3038         }
3039
3040         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3041
3042       } else {
3043         /* >32-bits, result on stack, and FSR0 points to beginning.
3044          * Fix stack when done */
3045         /* FIXME FIXME */
3046 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3047         while (size--) {
3048 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3049 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3050
3051           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3052           GpsuedoStkPtr++;
3053         }
3054
3055         /* fix stack */
3056         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3057         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3058         if(STACK_MODEL_LARGE) {
3059           emitSKPNC;
3060           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3061         }
3062       }
3063     } else {
3064       int areg = 0;             /* matching argument register */
3065
3066 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3067       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3068
3069
3070       /* its called from genReceive (probably) -- VR */
3071       /* I hope this code will not be called from somewhere else in the future!
3072        * We manually set the pseudo stack pointer in genReceive. - dw
3073        */
3074       if(!GpsuedoStkPtr && _G.useWreg) {
3075 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3076
3077         /* The last byte in the assignment is in W */
3078         if(areg <= GpsuedoStkPtr) {
3079           size--;
3080           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3081           offset++;
3082 //          debugf("receive from WREG\n", 0);
3083         }
3084         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3085       }
3086 //      GpsuedoStkPtr++;
3087       _G.stack_lat = AOP_SIZE(oper)-1;
3088
3089       while (size) {
3090         size--;
3091         GpsuedoStkPtr++;
3092         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3093 //        debugf("receive from STACK\n", 0);
3094         offset++;
3095       }
3096     }
3097 }
3098
3099
3100 /*-----------------------------------------------------------------*/
3101 /* genIpush - generate code for pushing this gets a little complex */
3102 /*-----------------------------------------------------------------*/
3103 static void genIpush (iCode *ic)
3104 {
3105 //  int size, offset=0;
3106
3107   FENTRY;
3108   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3109
3110   if(ic->parmPush) {
3111     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3112
3113     /* send to stack as normal */
3114     addSet(&_G.sendSet,ic);
3115 //    addSetHead(&_G.sendSet,ic);
3116     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3117   }
3118
3119
3120 #if 0
3121     int size, offset = 0 ;
3122     char *l;
3123
3124
3125     /* if this is not a parm push : ie. it is spill push
3126     and spill push is always done on the local stack */
3127     if (!ic->parmPush) {
3128
3129         /* and the item is spilt then do nothing */
3130         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3131             return ;
3132
3133         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3134         size = AOP_SIZE(IC_LEFT(ic));
3135         /* push it on the stack */
3136         while(size--) {
3137             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3138             if (*l == '#') {
3139                 MOVA(l);
3140                 l = "acc";
3141             }
3142             pic16_emitcode("push","%s",l);
3143         }
3144         return ;
3145     }
3146
3147     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3148 #endif
3149 }
3150
3151 /*-----------------------------------------------------------------*/
3152 /* genIpop - recover the registers: can happen only for spilling   */
3153 /*-----------------------------------------------------------------*/
3154 static void genIpop (iCode *ic)
3155 {
3156   FENTRY;
3157   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3158 #if 0
3159     int size,offset ;
3160
3161
3162     /* if the temp was not pushed then */
3163     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3164         return ;
3165
3166     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3167     size = AOP_SIZE(IC_LEFT(ic));
3168     offset = (size-1);
3169     while (size--)
3170         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3171                                    FALSE,TRUE));
3172
3173     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3174 #endif
3175 }
3176
3177 #if 0
3178 /*-----------------------------------------------------------------*/
3179 /* unsaverbank - restores the resgister bank from stack            */
3180 /*-----------------------------------------------------------------*/
3181 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3182 {
3183   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3184 #if 0
3185     int i;
3186     asmop *aop ;
3187     regs *r = NULL;
3188
3189     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3190     if (popPsw) {
3191         if (options.useXstack) {
3192             aop = newAsmop(0);
3193             r = getFreePtr(ic,&aop,FALSE);
3194
3195
3196             pic16_emitcode("mov","%s,_spx",r->name);
3197             pic16_emitcode("movx","a,@%s",r->name);
3198             pic16_emitcode("mov","psw,a");
3199             pic16_emitcode("dec","%s",r->name);
3200
3201         }else
3202             pic16_emitcode ("pop","psw");
3203     }
3204
3205     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3206         if (options.useXstack) {
3207             pic16_emitcode("movx","a,@%s",r->name);
3208             //pic16_emitcode("mov","(%s+%d),a",
3209             //       regspic16[i].base,8*bank+regspic16[i].offset);
3210             pic16_emitcode("dec","%s",r->name);
3211
3212         } else
3213           pic16_emitcode("pop",""); //"(%s+%d)",
3214         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3215     }
3216
3217     if (options.useXstack) {
3218
3219         pic16_emitcode("mov","_spx,%s",r->name);
3220         pic16_freeAsmop(NULL,aop,ic,TRUE);
3221
3222     }
3223 #endif
3224 }
3225
3226 /*-----------------------------------------------------------------*/
3227 /* saverbank - saves an entire register bank on the stack          */
3228 /*-----------------------------------------------------------------*/
3229 static void saverbank (int bank, iCode *ic, bool pushPsw)
3230 {
3231   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3232 #if 0
3233     int i;
3234     asmop *aop ;
3235     regs *r = NULL;
3236
3237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3238     if (options.useXstack) {
3239
3240         aop = newAsmop(0);
3241         r = getFreePtr(ic,&aop,FALSE);
3242         pic16_emitcode("mov","%s,_spx",r->name);
3243
3244     }
3245
3246     for (i = 0 ; i < pic16_nRegs ;i++) {
3247         if (options.useXstack) {
3248             pic16_emitcode("inc","%s",r->name);
3249             //pic16_emitcode("mov","a,(%s+%d)",
3250             //         regspic16[i].base,8*bank+regspic16[i].offset);
3251             pic16_emitcode("movx","@%s,a",r->name);
3252         } else
3253           pic16_emitcode("push","");// "(%s+%d)",
3254                      //regspic16[i].base,8*bank+regspic16[i].offset);
3255     }
3256
3257     if (pushPsw) {
3258         if (options.useXstack) {
3259             pic16_emitcode("mov","a,psw");
3260             pic16_emitcode("movx","@%s,a",r->name);
3261             pic16_emitcode("inc","%s",r->name);
3262             pic16_emitcode("mov","_spx,%s",r->name);
3263             pic16_freeAsmop (NULL,aop,ic,TRUE);
3264
3265         } else
3266             pic16_emitcode("push","psw");
3267
3268         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3269     }
3270     ic->bankSaved = 1;
3271 #endif
3272 }
3273 #endif  /* 0 */
3274
3275
3276 static int wparamCmp(void *p1, void *p2)
3277 {
3278   return (!strcmp((char *)p1, (char *)p2));
3279 }
3280
3281 int inWparamList(char *s)
3282 {
3283   return isinSetWith(wparamList, s, wparamCmp);
3284 }
3285
3286
3287 /*-----------------------------------------------------------------*/
3288 /* genCall - generates a call statement                            */
3289 /*-----------------------------------------------------------------*/
3290 static void genCall (iCode *ic)
3291 {
3292   sym_link *ftype;
3293   int stackParms=0;
3294   int use_wreg=0;
3295   int inwparam=0;
3296   char *fname;
3297
3298     FENTRY;
3299
3300     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3301     /* if caller saves & we have not saved then */
3302 //    if (!ic->regsSaved)
3303 //      saveRegisters(ic);
3304
3305         /* initialise stackParms for IPUSH pushes */
3306 //      stackParms = psuedoStkPtr;
3307 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3308     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3309     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3310
3311 #if 0
3312     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3313 #endif
3314
3315     /* if send set is not empty the assign */
3316     if (_G.sendSet) {
3317       iCode *sic;
3318       int psuedoStkPtr=-1;
3319       int firstTimeThruLoop = 1;
3320
3321
3322         /* reverse sendSet if function is not reentrant */
3323         if(!IFFUNC_ISREENT(ftype))
3324           _G.sendSet = reverseSet(_G.sendSet);
3325
3326         /* First figure how many parameters are getting passed */
3327         stackParms = 0;
3328         use_wreg = 0;
3329
3330         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3331           int size;
3332 //          int offset = 0;
3333
3334             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3335             size = AOP_SIZE(IC_LEFT(sic));
3336
3337             stackParms += size;
3338
3339             /* pass the last byte through WREG */
3340             if(inwparam) {
3341
3342               while (size--) {
3343                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3344                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3345                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3346
3347                 if(!firstTimeThruLoop) {
3348                   /* If this is not the first time we've been through the loop
3349                    * then we need to save the parameter in a temporary
3350                    * register. The last byte of the last parameter is
3351                    * passed in W. */
3352
3353                   pushw();
3354 //                  --psuedoStkPtr;             // sanity check
3355                   use_wreg = 1;
3356                 }
3357
3358                 firstTimeThruLoop=0;
3359
3360                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3361
3362 //                offset++;
3363               }
3364             } else {
3365               /* all arguments are passed via stack */
3366               use_wreg = 0;
3367
3368               while (size--) {
3369                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3370                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3371                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3372
3373 //                pushaop(AOP(IC_LEFT(sic)), size);
3374                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3375
3376                 if(!_G.resDirect)
3377                   pushw();
3378               }
3379             }
3380
3381             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3382           }
3383
3384           if(inwparam) {
3385             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3386               pushw();  /* save last parameter to stack if functions has varargs */
3387               use_wreg = 0;
3388             } else
3389               use_wreg = 1;
3390           } else use_wreg = 0;
3391
3392           _G.stackRegSet = _G.sendSet;
3393           _G.sendSet = NULL;
3394     }
3395
3396     /* make the call */
3397     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3398
3399     GpsuedoStkPtr=0;
3400
3401     /* if we need to assign a result value */
3402     if ((IS_ITEMP(IC_RESULT(ic))
3403           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3404               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3405         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3406
3407       _G.accInUse++;
3408       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3409       _G.accInUse--;
3410
3411       /* Must not assign an 8-bit result to a 16-bit variable;
3412        * this would use (used...) the uninitialized PRODL! */
3413       /* FIXME: Need a proper way to obtain size of function result type,
3414        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3415       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3416
3417       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3418                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3419
3420       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3421     }
3422
3423     if(!stackParms && ic->parmBytes) {
3424       stackParms = ic->parmBytes;
3425     }
3426
3427     stackParms -= use_wreg;
3428
3429     if(stackParms>0) {
3430       if(stackParms == 1) {
3431         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3432       } else {
3433         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3434         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3435       }
3436       if(STACK_MODEL_LARGE) {
3437         emitSKPNC;
3438         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3439       }
3440     }
3441
3442 #if 0
3443     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3444 #endif
3445
3446     /* adjust the stack for parameters if required */
3447 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3448
3449 #if 0
3450       /* if register bank was saved then pop them */
3451       if (ic->bankSaved)
3452         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3453
3454       /* if we hade saved some registers then unsave them */
3455       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3456         unsaveRegisters (ic);
3457 #endif
3458 }
3459
3460
3461
3462 /*-----------------------------------------------------------------*/
3463 /* genPcall - generates a call by pointer statement                */
3464 /*            new version, created from genCall - HJD              */
3465 /*-----------------------------------------------------------------*/
3466 static void genPcall (iCode *ic)
3467 {
3468   sym_link *fntype;
3469   int stackParms=0;
3470   symbol *retlbl = newiTempLabel(NULL);
3471   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3472
3473     FENTRY;
3474
3475     fntype = operandType( IC_LEFT(ic) )->next;
3476
3477     /* if send set is not empty the assign */
3478     if (_G.sendSet) {
3479       iCode *sic;
3480       int psuedoStkPtr=-1;
3481
3482       /* reverse sendSet if function is not reentrant */
3483       if(!IFFUNC_ISREENT(fntype))
3484         _G.sendSet = reverseSet(_G.sendSet);
3485
3486       stackParms = 0;
3487
3488       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3489         int size;
3490
3491           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3492           size = AOP_SIZE(IC_LEFT(sic));
3493           stackParms += size;
3494
3495           /* all parameters are passed via stack, since WREG is clobbered
3496            * by the calling sequence */
3497           while (size--) {
3498             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3499             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3500             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3501
3502             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3503             pushw();
3504           }
3505
3506           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3507       }
3508
3509       _G.stackRegSet = _G.sendSet;
3510       _G.sendSet = NULL;
3511     }
3512
3513     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3514
3515     // push return address
3516     // push $ on return stack, then replace with retlbl
3517
3518     /* Thanks to Thorsten Klose for pointing out that the following
3519      * snippet should be interrupt safe */
3520     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3521     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3522
3523     pic16_emitpcodeNULLop(POC_PUSH);
3524
3525     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3526     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3527     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3528     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3529     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3530     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3531
3532
3533     /* restore interrupt control register */
3534     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3535     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3536
3537     /* make the call by writing the pointer into pc */
3538     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3539     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3540
3541     // note: MOVFF to PCL not allowed
3542     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3543     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3544
3545
3546     /* return address is here: (X) */
3547     pic16_emitpLabelFORCE(retlbl->key);
3548
3549     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3550
3551     GpsuedoStkPtr=0;
3552     /* if we need assign a result value */
3553     if ((IS_ITEMP(IC_RESULT(ic))
3554           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3555               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3556         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3557
3558       _G.accInUse++;
3559       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3560       _G.accInUse--;
3561
3562       /* FIXME: Need proper way to obtain the function result's type.
3563        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3564       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3565
3566       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3567               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3568
3569       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3570     }
3571
3572 //    stackParms -= use_wreg;
3573
3574     if(stackParms>0) {
3575       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3576       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3577       if(STACK_MODEL_LARGE) {
3578         emitSKPNC;
3579         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3580       }
3581     }
3582 }
3583
3584 /*-----------------------------------------------------------------*/
3585 /* resultRemat - result  is rematerializable                       */
3586 /*-----------------------------------------------------------------*/
3587 static int resultRemat (iCode *ic)
3588 {
3589   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3590   if (SKIP_IC(ic) || ic->op == IFX)
3591     return 0;
3592
3593   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3594     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3595     if (sym->remat && !POINTER_SET(ic))
3596       return 1;
3597   }
3598
3599   return 0;
3600 }
3601
3602 #if 0
3603 /*-----------------------------------------------------------------*/
3604 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3605 /*-----------------------------------------------------------------*/
3606 static bool inExcludeList(char *s)
3607 {
3608   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3609     int i =0;
3610
3611     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3612     if (options.excludeRegs[i] &&
3613     STRCASECMP(options.excludeRegs[i],"none") == 0)
3614         return FALSE ;
3615
3616     for ( i = 0 ; options.excludeRegs[i]; i++) {
3617         if (options.excludeRegs[i] &&
3618         STRCASECMP(s,options.excludeRegs[i]) == 0)
3619             return TRUE;
3620     }
3621     return FALSE ;
3622 }
3623 #endif
3624
3625 /*-----------------------------------------------------------------*/
3626 /* genFunction - generated code for function entry                 */
3627 /*-----------------------------------------------------------------*/
3628 static void genFunction (iCode *ic)
3629 {
3630   symbol *sym;
3631   sym_link *ftype;
3632
3633     FENTRY;
3634     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3635
3636     pic16_labelOffset += (max_key+4);
3637     max_key=0;
3638     GpsuedoStkPtr=0;
3639     _G.nRegsSaved = 0;
3640
3641     ftype = operandType(IC_LEFT(ic));
3642     sym = OP_SYMBOL(IC_LEFT(ic));
3643
3644     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3645       /* create an absolute section at the interrupt vector:
3646        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3647       symbol *asym;
3648       char asymname[128];
3649       pBlock *apb;
3650
3651 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3652
3653         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3654           sprintf(asymname, "ivec_%s", sym->name);
3655         else
3656           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3657
3658         /* when an interrupt is declared as naked, do not emit the special
3659          * wrapper segment at vector address. The user should take care for
3660          * this instead. -- VR */
3661
3662         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3663           asym = newSymbol(asymname, 0);
3664           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3665           pic16_addpBlock( apb );
3666
3667           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3668           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3669           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3670           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3671           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3672
3673           /* mark the end of this tiny function */
3674           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3675         } else {
3676           sprintf(asymname, "%s", sym->rname);
3677         }
3678
3679         {
3680           absSym *abSym;
3681
3682             abSym = Safe_calloc(1, sizeof(absSym));
3683             strcpy(abSym->name, asymname);
3684
3685             switch( FUNC_INTNO(sym->type) ) {
3686               case 0: abSym->address = 0x000000; break;
3687               case 1: abSym->address = 0x000008; break;
3688               case 2: abSym->address = 0x000018; break;
3689
3690               default:
3691 //                fprintf(stderr, "no interrupt number is given\n");
3692                 abSym->address = -1; break;
3693             }
3694
3695             /* relocate interrupt vectors if needed */
3696             if(abSym->address != -1)
3697               abSym->address += pic16_options.ivt_loc;
3698
3699             addSet(&absSymSet, abSym);
3700         }
3701     }
3702
3703     /* create the function header */
3704     pic16_emitcode(";","-----------------------------------------");
3705     pic16_emitcode(";"," function %s",sym->name);
3706     pic16_emitcode(";","-----------------------------------------");
3707
3708     /* prevent this symbol from being emitted as 'extern' */
3709     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3710
3711     pic16_emitcode("","%s:",sym->rname);
3712     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3713
3714     {
3715       absSym *ab;
3716
3717         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3718           if(!strcmp(ab->name, sym->rname)) {
3719             pic16_pBlockConvert2Absolute(pb);
3720             break;
3721           }
3722         }
3723     }
3724
3725     if(IFFUNC_ISNAKED(ftype)) {
3726       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3727       return;
3728     }
3729
3730     /* if critical function then turn interrupts off */
3731     if (IFFUNC_ISCRITICAL(ftype)) {
3732       //pic16_emitcode("clr","ea");
3733     }
3734
3735     currFunc = sym;             /* update the currFunc symbol */
3736     _G.fregsUsed = sym->regsUsed;
3737     _G.sregsAlloc = newBitVect(128);
3738
3739
3740     /* if this is an interrupt service routine then
3741      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3742     if (IFFUNC_ISISR(sym->type)) {
3743         _G.usefastretfie = 1;   /* use shadow registers by default */
3744
3745         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3746         if(!FUNC_ISSHADOWREGS(sym->type)) {
3747           /* do not save WREG,STATUS,BSR for high priority interrupts
3748            * because they are stored in the hardware shadow registers already */
3749           _G.usefastretfie = 0;
3750           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3751           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3752           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3753         }
3754
3755         /* these should really be optimized somehow, because not all
3756          * interrupt handlers modify them */
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3758         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3759         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3762         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3763
3764 //        pic16_pBlockConvert2ISR(pb);
3765     }
3766
3767     /* emit code to setup stack frame if user enabled,
3768      * and function is not main() */
3769
3770 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3771     if(strcmp(sym->name, "main")) {
3772       if(0
3773         || !options.ommitFramePtr
3774 //        || sym->regsUsed
3775         || IFFUNC_ARGS(sym->type)
3776         || FUNC_HASSTACKPARM(sym->etype)
3777         ) {
3778         /* setup the stack frame */
3779         if(STACK_MODEL_LARGE)
3780           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3781         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3782
3783         if(STACK_MODEL_LARGE)
3784           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3785         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3786       }
3787     }
3788
3789     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3790           && sym->stack) {
3791
3792       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3793
3794       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3795       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3796       emitSKPC;
3797       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3798     }
3799
3800     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3801       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3802         _G.useWreg = 0;
3803       else
3804         _G.useWreg = 1;
3805     } else
3806       _G.useWreg = 0;
3807
3808     /* if callee-save to be used for this function
3809      * then save the registers being used in this function */
3810 //    if (IFFUNC_CALLEESAVES(sym->type))
3811     if(strcmp(sym->name, "main")) {
3812       int i;
3813
3814         /* if any registers used */
3815         if (sym->regsUsed) {
3816                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3817
3818           if(!xinst) {
3819             /* save the registers used */
3820             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3821             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3822               if (bitVectBitValue(sym->regsUsed,i)) {
3823 #if 0
3824                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3825 #endif
3826                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3827                 _G.nRegsSaved++;
3828
3829                 if(!pic16_regWithIdx(i)->wasUsed) {
3830                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3831                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3832                   pic16_regWithIdx(i)->wasUsed = 1;
3833                 }
3834               }
3835             }
3836           } else {
3837
3838             /* xinst */
3839             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3840             for(i=0;i<sym->regsUsed->size;i++) {
3841               if(bitVectBitValue(sym->regsUsed, i)) {
3842                 _G.nRegsSaved++;
3843               }
3844             }
3845
3846 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3847           }
3848
3849           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3850
3851         }
3852     }
3853
3854     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3855 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genEndFunction - generates epilogue for functions               */
3860 /*-----------------------------------------------------------------*/
3861 static void genEndFunction (iCode *ic)
3862 {
3863   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3864
3865     FENTRY;
3866
3867     if(IFFUNC_ISNAKED(sym->type)) {
3868       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3869       return;
3870     }
3871
3872     _G.stack_lat = 0;
3873
3874     /* add code for ISCRITICAL */
3875     if(IFFUNC_ISCRITICAL(sym->type)) {
3876       /* if critical function, turn on interrupts */
3877
3878       /* TODO: add code here -- VR */
3879     }
3880
3881 //    sym->regsUsed = _G.fregsUsed;
3882
3883     /* now we need to restore the registers */
3884     /* if any registers used */
3885
3886     /* first restore registers that might be used for stack access */
3887     if(_G.sregsAllocSet) {
3888     regs *sr;
3889
3890       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3891       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3892         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3893       }
3894     }
3895
3896     if (strcmp(sym->name, "main") && sym->regsUsed) {
3897       int i;
3898
3899         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3900         /* restore registers used */
3901         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3902         for ( i = sym->regsUsed->size; i >= 0; i--) {
3903           if (bitVectBitValue(sym->regsUsed,i)) {
3904             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3905             _G.nRegsSaved--;
3906           }
3907         }
3908         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3909     }
3910
3911
3912
3913     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3914           && sym->stack) {
3915       if (sym->stack == 1) {
3916         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3917         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3918       } else {
3919         // we have to add more than one...
3920         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3921         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3922         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3923         emitSKPNC;
3924         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3925         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3926         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3927       }
3928     }
3929
3930     if(strcmp(sym->name, "main")) {
3931       if(0
3932         || !options.ommitFramePtr
3933 //        || sym->regsUsed
3934         || IFFUNC_ARGS(sym->type)
3935         || FUNC_HASSTACKPARM(sym->etype)
3936         ) {
3937         /* restore stack frame */
3938         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3939         if(STACK_MODEL_LARGE)
3940           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3941       }
3942     }
3943
3944     _G.useWreg = 0;
3945
3946     if (IFFUNC_ISISR(sym->type)) {
3947       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3948       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3949       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3950       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3951       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3952       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3953
3954       if(!FUNC_ISSHADOWREGS(sym->type)) {
3955         /* do not restore interrupt vector for WREG,STATUS,BSR
3956          * for high priority interrupt, see genFunction */
3957         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3958         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3959         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3960       }
3961 //      _G.interruptvector = 0;         /* sanity check */
3962
3963
3964       /* if debug then send end of function */
3965 /*      if (options.debug && currFunc)  */
3966       if (currFunc) {
3967         debugFile->writeEndFunction (currFunc, ic, 1);
3968       }
3969
3970       if(_G.usefastretfie)
3971         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3972       else
3973         pic16_emitpcodeNULLop(POC_RETFIE);
3974
3975       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3976
3977       _G.usefastretfie = 0;
3978       return;
3979     }
3980
3981     if (IFFUNC_ISCRITICAL(sym->type)) {
3982       pic16_emitcode("setb","ea");
3983     }
3984
3985     /* if debug then send end of function */
3986     if (currFunc) {
3987       debugFile->writeEndFunction (currFunc, ic, 1);
3988     }
3989
3990     /* insert code to restore stack frame, if user enabled it
3991      * and function is not main() */
3992
3993
3994     pic16_emitpcodeNULLop(POC_RETURN);
3995
3996     /* Mark the end of a function */
3997     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3998 }
3999
4000
4001 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4002 {
4003   unsigned long lit=1;
4004   operand *op;
4005
4006     op = IC_LEFT(ic);
4007
4008     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4009     if(AOP_TYPE(op) == AOP_LIT) {
4010       if(!IS_FLOAT(operandType( op ))) {
4011         lit = ulFromVal (AOP(op)->aopu.aop_lit);
4012       } else {
4013         union {
4014           unsigned long lit_int;
4015           float lit_float;
4016         } info;
4017
4018         /* take care if literal is a float */
4019         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4020         lit = info.lit_int;
4021       }
4022     }
4023
4024     if (AOP_TYPE(op) == AOP_LIT) {
4025       /* FIXME: broken for
4026        *   char __at(0x456) foo;
4027        *   return &foo;
4028        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4029       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4030     } else if (AOP_TYPE(op) == AOP_PCODE
4031                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4032       /* char *s= "aaa"; return s; */
4033       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4034        *      that the generic pointer is interpreted correctly
4035        *      as referring to __code space, but this is fragile! */
4036       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4037       /* XXX: should check that dest != WREG */
4038       pic16_emitpcode(POC_MOVWF, dest);
4039     } else {
4040       if(dest->type == PO_WREG && (offset == 0)) {
4041         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4042         return;
4043       }
4044       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4045     }
4046 }
4047
4048 /*-----------------------------------------------------------------*/
4049 /* genRet - generate code for return statement                     */
4050 /*-----------------------------------------------------------------*/
4051 static void genRet (iCode *ic)
4052 {
4053   int size;
4054   operand *left;
4055
4056     FENTRY;
4057         /* if we have no return value then
4058          * just generate the "ret" */
4059
4060         if (!IC_LEFT(ic))
4061                 goto jumpret;
4062
4063         /* we have something to return then
4064          * move the return value into place */
4065         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4066         size = AOP_SIZE(IC_LEFT(ic));
4067
4068         if(size <= 4) {
4069           if(size>3)
4070             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4071
4072           if(size>2)
4073             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4074
4075           if(size>1)
4076             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4077
4078           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4079
4080         } else {
4081                 /* >32-bits, setup stack and FSR0 */
4082                 while (size--) {
4083 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4084 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4085
4086                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4087
4088 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4089                         GpsuedoStkPtr++;
4090                 }
4091
4092                 /* setup FSR0 */
4093                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4094                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4095
4096                 if(STACK_MODEL_LARGE) {
4097                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4098                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4099                 } else {
4100                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4101                 }
4102         }
4103
4104 #if 0
4105         /* old code, left here for reference -- VR */
4106         while (size--) {
4107           char *l ;
4108
4109                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4110                         /* #NOCHANGE */
4111                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4112                         pic16_emitpcomment("push %s",l);
4113                         pushed++;
4114                 } else {
4115                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4116                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4117                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);
4118
4119                         if (strcmp(fReturn[offset],l)) {
4120                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4121                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4122                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4123                                 } else {
4124                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4125                                 }
4126
4127                                 if(size) {
4128                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4129                                 }
4130                                 offset++;
4131                         }
4132                 }
4133         }
4134
4135         if (pushed) {
4136                 while(pushed) {
4137                         pushed--;
4138                         if (strcmp(fReturn[pushed],"a"))
4139                                 pic16_emitcode("pop",fReturn[pushed]);
4140                         else
4141                                 pic16_emitcode("pop","acc");
4142                 }
4143         }
4144 #endif
4145
4146
4147         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4148
4149 jumpret:
4150         /* generate a jump to the return label
4151          * if the next is not the return statement */
4152         if (!(ic->next && ic->next->op == LABEL
4153                 && IC_LABEL(ic->next) == returnLabel)) {
4154
4155                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4156                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4157         }
4158 }
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genLabel - generates a label                                    */
4162 /*-----------------------------------------------------------------*/
4163 static void genLabel (iCode *ic)
4164 {
4165   FENTRY;
4166
4167   /* special case never generate */
4168   if (IC_LABEL(ic) == entryLabel)
4169     return ;
4170
4171   pic16_emitpLabel(IC_LABEL(ic)->key);
4172 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4173 }
4174
4175 /*-----------------------------------------------------------------*/
4176 /* genGoto - generates a goto                                      */
4177 /*-----------------------------------------------------------------*/
4178 //tsd
4179 static void genGoto (iCode *ic)
4180 {
4181   FENTRY;
4182   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4183 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4184 }
4185
4186
4187 /*-----------------------------------------------------------------*/
4188 /* genMultbits :- multiplication of bits                           */
4189 /*-----------------------------------------------------------------*/
4190 static void genMultbits (operand *left,
4191                          operand *right,
4192                          operand *result)
4193 {
4194   FENTRY;
4195
4196   if(!pic16_sameRegs(AOP(result),AOP(right)))
4197     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4198
4199   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4200   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4201   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4202
4203 }
4204
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genMultOneByte : 8 bit multiplication & division                */
4208 /*-----------------------------------------------------------------*/
4209 static void genMultOneByte (operand *left,
4210                             operand *right,
4211                             operand *result)
4212 {
4213
4214   FENTRY;
4215   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4217
4218   /* (if two literals, the value is computed before) */
4219   /* if one literal, literal on the right */
4220   if (AOP_TYPE(left) == AOP_LIT){
4221     operand *t = right;
4222     right = left;
4223     left = t;
4224   }
4225
4226         /* size is already checked in genMult == 1 */
4227 //      size = AOP_SIZE(result);
4228
4229         if (AOP_TYPE(right) == AOP_LIT){
4230                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4231                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
4232                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
4233                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4234         } else {
4235                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4236                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
4237                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
4238                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4239         }
4240
4241         pic16_genMult8X8_n (left, right,result);
4242 }
4243
4244 #if 0
4245 /*-----------------------------------------------------------------*/
4246 /* genMultOneWord : 16 bit multiplication                          */
4247 /*-----------------------------------------------------------------*/
4248 static void genMultOneWord (operand *left,
4249                             operand *right,
4250                             operand *result)
4251 {
4252   FENTRY;
4253   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4254   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4255
4256   /* (if two literals, the value is computed before)
4257    * if one literal, literal on the right */
4258   if (AOP_TYPE(left) == AOP_LIT){
4259     operand *t = right;
4260     right = left;
4261     left = t;
4262   }
4263
4264   /* size is checked already == 2 */
4265 //  size = AOP_SIZE(result);
4266
4267   if (AOP_TYPE(right) == AOP_LIT) {
4268     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4269       pic16_aopGet(AOP(right),0,FALSE,FALSE),
4270       pic16_aopGet(AOP(left),0,FALSE,FALSE),
4271       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4272   } else {
4273     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4274       pic16_aopGet(AOP(right),0,FALSE,FALSE),
4275       pic16_aopGet(AOP(left),0,FALSE,FALSE),
4276       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4277   }
4278
4279   pic16_genMult16X16_16(left, right,result);
4280 }
4281 #endif
4282
4283 #if 0
4284 /*-----------------------------------------------------------------*/
4285 /* genMultOneLong : 32 bit multiplication                          */
4286 /*-----------------------------------------------------------------*/
4287 static void genMultOneLong (operand *left,
4288                             operand *right,
4289                             operand *result)
4290 {
4291   FENTRY;
4292   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4293   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4294
4295   /* (if two literals, the value is computed before)
4296    * if one literal, literal on the right */
4297   if (AOP_TYPE(left) == AOP_LIT){
4298     operand *t = right;
4299     right = left;
4300     left = t;
4301   }
4302
4303   /* size is checked already == 4 */
4304 //  size = AOP_SIZE(result);
4305
4306   if (AOP_TYPE(right) == AOP_LIT) {
4307     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
4308         pic16_aopGet(AOP(right),0,FALSE,FALSE),
4309         pic16_aopGet(AOP(left),0,FALSE,FALSE),
4310         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4311   } else {
4312     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
4313         pic16_aopGet(AOP(right),0,FALSE,FALSE),
4314         pic16_aopGet(AOP(left),0,FALSE,FALSE),
4315         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4316   }
4317
4318   pic16_genMult32X32_32(left, right,result);
4319 }
4320 #endif
4321
4322
4323
4324 /*-----------------------------------------------------------------*/
4325 /* genMult - generates code for multiplication                     */
4326 /*-----------------------------------------------------------------*/
4327 static void genMult (iCode *ic)
4328 {
4329   operand *left = IC_LEFT(ic);
4330   operand *right = IC_RIGHT(ic);
4331   operand *result= IC_RESULT(ic);
4332
4333     FENTRY;
4334         /* assign the amsops */
4335         pic16_aopOp (left,ic,FALSE);
4336         pic16_aopOp (right,ic,FALSE);
4337         pic16_aopOp (result,ic,TRUE);
4338
4339         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4340
4341         /* special cases first *
4342         * both are bits */
4343         if (AOP_TYPE(left) == AOP_CRY
4344                 && AOP_TYPE(right)== AOP_CRY) {
4345                 genMultbits(left,right,result);
4346           goto release ;
4347         }
4348
4349         /* if both are of size == 1 */
4350         if(AOP_SIZE(left) == 1
4351                 && AOP_SIZE(right) == 1) {
4352                 genMultOneByte(left,right,result);
4353           goto release ;
4354         }
4355
4356 #if 0
4357         /* if both are of size == 2 */
4358         if(AOP_SIZE(left) == 2
4359                 && AOP_SIZE(right) == 2) {
4360                 genMultOneWord(left, right, result);
4361           goto release;
4362         }
4363
4364         /* if both are of size == 4 */
4365         if(AOP_SIZE(left) == 4
4366                 && AOP_SIZE(right) == 4) {
4367                 genMultOneLong(left, right, result);
4368           goto release;
4369         }
4370 #endif
4371
4372         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4373         assert( !"Multiplication should have been transformed into function call!" );
4374
4375         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4376
4377
4378         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4379         /* should have been converted to function call */
4380         assert(0) ;
4381
4382 release :
4383         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4385         pic16_freeAsmop(result,NULL,ic,TRUE);
4386 }
4387
4388 #if 0
4389 /*-----------------------------------------------------------------*/
4390 /* genDivbits :- division of bits                                  */
4391 /*-----------------------------------------------------------------*/
4392 static void genDivbits (operand *left,
4393                         operand *right,
4394                         operand *result)
4395 {
4396   char *l;
4397
4398     FENTRY;
4399     /* the result must be bit */
4400     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4401     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4402
4403     MOVA(l);
4404
4405     pic16_emitcode("div","ab");
4406     pic16_emitcode("rrc","a");
4407     pic16_aopPut(AOP(result),"c",0);
4408 }
4409
4410 /*-----------------------------------------------------------------*/
4411 /* genDivOneByte : 8 bit division                                  */
4412 /*-----------------------------------------------------------------*/
4413 static void genDivOneByte (operand *left,
4414                            operand *right,
4415                            operand *result)
4416 {
4417   sym_link *opetype = operandType(result);
4418   char *l ;
4419   symbol *lbl ;
4420   int size,offset;
4421
4422         /* result = divident / divisor
4423          * - divident may be a register or a literal,
4424          * - divisor may be a register or a literal,
4425          * so there are 3 cases (literal / literal is optimized
4426          * by the front-end) to handle.
4427          * In addition we must handle signed and unsigned, which
4428          * result in 6 final different cases -- VR */
4429
4430     FENTRY;
4431
4432     size = AOP_SIZE(result) - 1;
4433     offset = 1;
4434     /* signed or unsigned */
4435     if (SPEC_USIGN(opetype)) {
4436       pCodeOp *pct1,    /* count */
4437                 *pct2,  /* reste */
4438                 *pct3;  /* temp */
4439       symbol *label1, *label2, *label3;;
4440
4441
4442         /* unsigned is easy */
4443
4444         pct1 = pic16_popGetTempReg(1);
4445         pct2 = pic16_popGetTempReg(1);
4446         pct3 = pic16_popGetTempReg(1);
4447
4448         label1 = newiTempLabel(NULL);
4449         label2 = newiTempLabel(NULL);
4450         label3 = newiTempLabel(NULL);
4451
4452         /* the following algorithm is extracted from divuint.c */
4453
4454         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4455         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4456
4457         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4458
4459         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4460
4461         pic16_emitpLabel(label1->key);
4462
4463         emitCLRC;
4464         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4465
4466
4467         emitCLRC;
4468         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4469
4470
4471         emitSKPNC;
4472         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4473
4474         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4475         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4476
4477         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4478         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4479         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4480
4481         pic16_emitpLabel( label3->key );
4482         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4483         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4484
4485
4486
4487         pic16_emitpLabel(label2->key);
4488         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4489         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4490         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4491
4492         /* result is in wreg */
4493         if(AOP_TYPE(result) != AOP_ACC)
4494                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4495
4496         pic16_popReleaseTempReg( pct3, 1);
4497         pic16_popReleaseTempReg( pct2, 1);
4498         pic16_popReleaseTempReg( pct1, 1);
4499
4500         return ;
4501     }
4502
4503     /* signed is a little bit more difficult */
4504
4505     /* save the signs of the operands */
4506     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4507     MOVA(l);
4508     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4509     pic16_emitcode("push","acc"); /* save it on the stack */
4510
4511     /* now sign adjust for both left & right */
4512     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4513     MOVA(l);
4514     lbl = newiTempLabel(NULL);
4515     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4516     pic16_emitcode("cpl","a");
4517     pic16_emitcode("inc","a");
4518     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4519     pic16_emitcode("mov","b,a");
4520
4521     /* sign adjust left side */
4522     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4523     MOVA(l);
4524
4525     lbl = newiTempLabel(NULL);
4526     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4527     pic16_emitcode("cpl","a");
4528     pic16_emitcode("inc","a");
4529     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4530
4531     /* now the division */
4532     pic16_emitcode("div","ab");
4533     /* we are interested in the lower order
4534     only */
4535     pic16_emitcode("mov","b,a");
4536     lbl = newiTempLabel(NULL);
4537     pic16_emitcode("pop","acc");
4538     /* if there was an over flow we don't
4539     adjust the sign of the result */
4540     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4541     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4542     CLRC;
4543     pic16_emitcode("clr","a");
4544     pic16_emitcode("subb","a,b");
4545     pic16_emitcode("mov","b,a");
4546     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4547
4548     /* now we are done */
4549     pic16_aopPut(AOP(result),"b",0);
4550     if(size > 0){
4551         pic16_emitcode("mov","c,b.7");
4552         pic16_emitcode("subb","a,acc");
4553     }
4554     while (size--)
4555         pic16_aopPut(AOP(result),"a",offset++);
4556
4557 }
4558 #endif
4559
4560 /*-----------------------------------------------------------------*/
4561 /* genDiv - generates code for division                            */
4562 /*-----------------------------------------------------------------*/
4563 static void genDiv (iCode *ic)
4564 {
4565     operand *left = IC_LEFT(ic);
4566     operand *right = IC_RIGHT(ic);
4567     operand *result= IC_RESULT(ic);
4568     int negated = 0;
4569     int leftVal = 0, rightVal = 0;
4570     int signedLits = 0;
4571     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4572     int op = 0;
4573
4574         /* Division is a very lengthy algorithm, so it is better
4575          * to call support routines than inlining algorithm.
4576          * Division functions written here just in case someone
4577          * wants to inline and not use the support libraries -- VR */
4578
4579     FENTRY;
4580
4581     /* assign the amsops */
4582     pic16_aopOp (left,ic,FALSE);
4583     pic16_aopOp (right,ic,FALSE);
4584     pic16_aopOp (result,ic,TRUE);
4585
4586     if (ic->op == '/')
4587       op = 0;
4588     else if (ic->op == '%')
4589       op = 1;
4590     else
4591       assert( !"invalid operation requested in genDivMod" );
4592
4593     /* get literal values */
4594     if (IS_VALOP(left)) {
4595       leftVal = (int) ulFromVal ( OP_VALUE(left) );
4596       assert( leftVal >= -128 && leftVal < 256 );
4597       if (leftVal < 0) { signedLits++; }
4598     }
4599     if (IS_VALOP(right)) {
4600       rightVal = (int) ulFromVal ( OP_VALUE(right) );
4601       assert( rightVal >= -128 && rightVal < 256 );
4602       if (rightVal < 0) { signedLits++; }
4603     }
4604
4605     /* We should only come here to convert all
4606      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4607      * with exactly one operand being s8_t into
4608      * u8_t x u8_t -> u8_t. All other cases should have been
4609      * turned into calls to support routines beforehand... */
4610     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4611         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4612     {
4613       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4614           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4615       {
4616         /* Both operands are signed or negative, use _divschar
4617          * instead of _divuchar */
4618         pushaop(AOP(right), 0);
4619         pushaop(AOP(left), 0);
4620
4621         /* call _divschar */
4622         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4623
4624         {
4625           symbol *sym;
4626           sym = newSymbol( functions[op][0], 0 );
4627           sym->used++;
4628           strcpy(sym->rname, functions[op][0]);
4629           checkAddSym(&externs, sym);
4630         }
4631
4632         /* assign result */
4633         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4634         if (AOP_SIZE(result) > 1)
4635         {
4636           pic16_emitpcode(POC_MOVFF,
4637               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4638                 pic16_popGet(AOP(result), 1)));
4639           /* sign extend */
4640           pic16_addSign(result, 2, 1);
4641         }
4642
4643         /* clean up stack */
4644         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4645         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4646
4647         goto release;
4648       }
4649
4650       /* push right operand */
4651       if (IS_VALOP(right)) {
4652         if (rightVal < 0) {
4653           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4654           negated++;
4655         } else {
4656           pushaop(AOP(right), 0);
4657         }
4658       } else if (!IS_UNSIGNED(operandType(right))) {
4659         pic16_mov2w(AOP(right), 0);
4660         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4661         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4662         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4663         negated++;
4664       } else {
4665         pushaop(AOP(right), 0);
4666       }
4667
4668       /* push left operand */
4669       if (IS_VALOP(left)) {
4670         if (leftVal < 0) {
4671           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4672           negated++;
4673         } else {
4674           pushaop(AOP(left), 0);
4675         }
4676       } else if (!IS_UNSIGNED(operandType(left))) {
4677         pic16_mov2w(AOP(left),0);
4678         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4679         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4680         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4681         negated++;
4682       } else {
4683         pushaop(AOP(left), 0);
4684       }
4685
4686       /* call _divuchar */
4687       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4688
4689       {
4690         symbol *sym;
4691         sym = newSymbol( functions[op][1], 0 );
4692         sym->used++;
4693         strcpy(sym->rname, functions[op][1]);
4694         checkAddSym(&externs, sym);
4695       }
4696
4697       /* Revert negation(s) from above.
4698        * This is inefficient: if both operands are negative, this
4699        * should not touch WREG. However, determining that exactly
4700        * one operand was negated costs at least 3 instructions,
4701        * so there is nothing to be gained here, is there?
4702        *
4703        * I negate WREG because either operand might share registers with
4704        * result, so assigning first might destroy an operand. */
4705
4706       /* For the modulus operator, (a/b)*b == a shall hold.
4707        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4708        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4709        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4710        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4711        * Only invert the result if the left operand is negative (sigh).
4712        */
4713       if (AOP_SIZE(result) <= 1 || !negated)
4714       {
4715         if (ic->op == '/')
4716         {
4717           if (IS_VALOP(right)) {
4718             if (rightVal < 0) {
4719               /* we negated this operand above */
4720               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4721             }
4722           } else if (!IS_UNSIGNED(operandType(right))) {
4723             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4724             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4725           }
4726         }
4727
4728         if (IS_VALOP(left)) {
4729           if (leftVal < 0) {
4730             /* we negated this operand above */
4731             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4732           }
4733         } else if (!IS_UNSIGNED(operandType(left))) {
4734           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4735           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4736         }
4737
4738         /* Move result to destination. */
4739         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4740
4741         /* Zero-extend:  no operand was signed (or result is just a byte). */
4742         pic16_addSign(result, 1, 0);
4743       } else {
4744         assert( AOP_SIZE(result) > 1 );
4745         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4746         if (ic->op == '/')
4747         {
4748           if (IS_VALOP(right)) {
4749             if (rightVal < 0) {
4750               /* we negated this operand above */
4751               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4752             }
4753           } else if (!IS_UNSIGNED(operandType(right))) {
4754             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4755             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4756           }
4757         }
4758
4759         if (IS_VALOP(left)) {
4760           if (leftVal < 0) {
4761             /* we negated this operand above */
4762             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4763           }
4764         } else if (!IS_UNSIGNED(operandType(left))) {
4765           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4766           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4767         }
4768
4769         /* Move result to destination. */
4770         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4771
4772         /* Negate result if required. */
4773         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4774         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4775
4776         /* Sign-extend. */
4777         pic16_addSign(result, 2, 1);
4778       }
4779
4780       /* clean up stack */
4781       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4782       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4783       goto release;
4784     }
4785
4786 #if 0
4787     /* special cases first */
4788     /* both are bits */
4789     if (AOP_TYPE(left) == AOP_CRY &&
4790         AOP_TYPE(right)== AOP_CRY) {
4791         genDivbits(left,right,result);
4792         goto release ;
4793     }
4794
4795     /* if both are of size == 1 */
4796     if (AOP_SIZE(left) == 1 &&
4797         AOP_SIZE(right) == 1 ) {
4798         genDivOneByte(left,right,result);
4799         goto release ;
4800     }
4801 #endif
4802
4803     /* should have been converted to function call */
4804     assert(0);
4805 release :
4806     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4808     pic16_freeAsmop(result,NULL,ic,TRUE);
4809 }
4810
4811 #if 0
4812 /*-----------------------------------------------------------------*/
4813 /* genModbits :- modulus of bits                                   */
4814 /*-----------------------------------------------------------------*/
4815 static void genModbits (operand *left,
4816                         operand *right,
4817                         operand *result)
4818 {
4819   char *l;
4820
4821     FENTRY;
4822
4823     werror(W_POSSBUG2, __FILE__, __LINE__);
4824     /* the result must be bit */
4825     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4826     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4827
4828     MOVA(l);
4829
4830     pic16_emitcode("div","ab");
4831     pic16_emitcode("mov","a,b");
4832     pic16_emitcode("rrc","a");
4833     pic16_aopPut(AOP(result),"c",0);
4834 }
4835
4836 /*-----------------------------------------------------------------*/
4837 /* genModOneByte : 8 bit modulus                                   */
4838 /*-----------------------------------------------------------------*/
4839 static void genModOneByte (operand *left,
4840                            operand *right,
4841                            operand *result)
4842 {
4843   sym_link *opetype = operandType(result);
4844   char *l ;
4845   symbol *lbl ;
4846
4847     FENTRY;
4848     werror(W_POSSBUG2, __FILE__, __LINE__);
4849
4850     /* signed or unsigned */
4851     if (SPEC_USIGN(opetype)) {
4852         /* unsigned is easy */
4853         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4854         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4855         MOVA(l);
4856         pic16_emitcode("div","ab");
4857         pic16_aopPut(AOP(result),"b",0);
4858         return ;
4859     }
4860
4861     /* signed is a little bit more difficult */
4862
4863     /* save the signs of the operands */
4864     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4865     MOVA(l);
4866
4867     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4868     pic16_emitcode("push","acc"); /* save it on the stack */
4869
4870     /* now sign adjust for both left & right */
4871     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4872     MOVA(l);
4873
4874     lbl = newiTempLabel(NULL);
4875     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4876     pic16_emitcode("cpl","a");
4877     pic16_emitcode("inc","a");
4878     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4879     pic16_emitcode("mov","b,a");
4880
4881     /* sign adjust left side */
4882     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4883     MOVA(l);
4884
4885     lbl = newiTempLabel(NULL);
4886     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4887     pic16_emitcode("cpl","a");
4888     pic16_emitcode("inc","a");
4889     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4890
4891     /* now the multiplication */
4892     pic16_emitcode("div","ab");
4893     /* we are interested in the lower order
4894     only */
4895     lbl = newiTempLabel(NULL);
4896     pic16_emitcode("pop","acc");
4897     /* if there was an over flow we don't
4898     adjust the sign of the result */
4899     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4900     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4901     CLRC ;
4902     pic16_emitcode("clr","a");
4903     pic16_emitcode("subb","a,b");
4904     pic16_emitcode("mov","b,a");
4905     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4906
4907     /* now we are done */
4908     pic16_aopPut(AOP(result),"b",0);
4909
4910 }
4911 #endif
4912
4913 /*-----------------------------------------------------------------*/
4914 /* genMod - generates code for division                            */
4915 /*-----------------------------------------------------------------*/
4916 static void genMod (iCode *ic)
4917 {
4918   /* Task deferred to genDiv */
4919   genDiv(ic);
4920 #if 0
4921   operand *left = IC_LEFT(ic);
4922   operand *right = IC_RIGHT(ic);
4923   operand *result= IC_RESULT(ic);
4924
4925     FENTRY;
4926
4927     /* assign the amsops */
4928     pic16_aopOp (left,ic,FALSE);
4929     pic16_aopOp (right,ic,FALSE);
4930     pic16_aopOp (result,ic,TRUE);
4931
4932     /* special cases first */
4933     /* both are bits */
4934     if (AOP_TYPE(left) == AOP_CRY &&
4935         AOP_TYPE(right)== AOP_CRY) {
4936         genModbits(left,right,result);
4937         goto release ;
4938     }
4939
4940     /* if both are of size == 1 */
4941     if (AOP_SIZE(left) == 1 &&
4942         AOP_SIZE(right) == 1 ) {
4943         genModOneByte(left,right,result);
4944         goto release ;
4945     }
4946
4947     /* should have been converted to function call */
4948     assert(0);
4949
4950 release :
4951     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4953     pic16_freeAsmop(result,NULL,ic,TRUE);
4954 #endif
4955 }
4956
4957 /*-----------------------------------------------------------------*/
4958 /* genIfxJump :- will create a jump depending on the ifx           */
4959 /*-----------------------------------------------------------------*/
4960 /*
4961   note: May need to add parameter to indicate when a variable is in bit space.
4962 */
4963 static void genIfxJump (iCode *ic, char *jval)
4964 {
4965   FENTRY;
4966
4967     /* if true label then we jump if condition
4968     supplied is true */
4969     if ( IC_TRUE(ic) ) {
4970
4971         if(strcmp(jval,"a") == 0)
4972           emitSKPZ;
4973         else if (strcmp(jval,"c") == 0)
4974           emitSKPNC;
4975         else {
4976           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4977           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4978         }
4979
4980         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4981         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4982
4983     }
4984     else {
4985         /* false label is present */
4986         if(strcmp(jval,"a") == 0)
4987           emitSKPNZ;
4988         else if (strcmp(jval,"c") == 0)
4989           emitSKPC;
4990         else {
4991           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4992           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4993         }
4994
4995         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4996         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4997
4998     }
4999
5000
5001     /* mark the icode as generated */
5002     ic->generated = 1;
5003 }
5004
5005 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5006 {
5007   FENTRY;
5008
5009     /* if true label then we jump if condition
5010     supplied is true */
5011     if ( IC_TRUE(ic) ) {
5012       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5013       pic16_emitpcode(POC_BTFSC, jop);
5014
5015       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5016       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5017
5018     } else {
5019       /* false label is present */
5020       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5021       pic16_emitpcode(POC_BTFSS, jop);
5022
5023       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5024       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5025     }
5026
5027
5028     /* mark the icode as generated */
5029     ic->generated = 1;
5030 }
5031
5032 #if 0
5033 // not needed ATM
5034
5035 /*-----------------------------------------------------------------*/
5036 /* genSkip                                                         */
5037 /*-----------------------------------------------------------------*/
5038 static void genSkip(iCode *ifx,int status_bit)
5039 {
5040   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5041   if(!ifx)
5042     return;
5043
5044   if ( IC_TRUE(ifx) ) {
5045     switch(status_bit) {
5046     case 'z':
5047       emitSKPNZ;
5048       break;
5049
5050     case 'c':
5051       emitSKPNC;
5052       break;
5053
5054     case 'd':
5055       emitSKPDC;
5056       break;
5057
5058     }
5059
5060     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5061     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5062
5063   } else {
5064
5065     switch(status_bit) {
5066
5067     case 'z':
5068       emitSKPZ;
5069       break;
5070
5071     case 'c':
5072       emitSKPC;
5073       break;
5074
5075     case 'd':
5076       emitSKPDC;
5077       break;
5078     }
5079     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5080     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5081
5082   }
5083
5084 }
5085 #endif
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genSkipc                                                        */
5089 /*-----------------------------------------------------------------*/
5090 static void genSkipc(resolvedIfx *rifx)
5091 {
5092   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5093
5094   if(!rifx)
5095     return;
5096
5097   if(rifx->condition)
5098     emitSKPNC;
5099   else
5100     emitSKPC;
5101
5102   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5103   rifx->generated = 1;
5104 }
5105
5106 #if !(USE_SIMPLE_GENCMP)
5107 /*-----------------------------------------------------------------*/
5108 /* genSkipz2                                                       */
5109 /*-----------------------------------------------------------------*/
5110 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5111 {
5112   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5113
5114   if(!rifx)
5115     return;
5116
5117   if( (rifx->condition ^ invert_condition) & 1)
5118     emitSKPZ;
5119   else
5120     emitSKPNZ;
5121
5122   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5123   rifx->generated = 1;
5124 }
5125 #endif
5126
5127 #if 0
5128 /*-----------------------------------------------------------------*/
5129 /* genSkipz                                                        */
5130 /*-----------------------------------------------------------------*/
5131 static void genSkipz(iCode *ifx, int condition)
5132 {
5133   if(!ifx)
5134     return;
5135
5136   if(condition)
5137     emitSKPNZ;
5138   else
5139     emitSKPZ;
5140
5141   if ( IC_TRUE(ifx) )
5142     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5143   else
5144     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5145
5146   if ( IC_TRUE(ifx) )
5147     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5148   else
5149     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5150
5151 }
5152 #endif
5153
5154 #if !(USE_SIMPLE_GENCMP)
5155 /*-----------------------------------------------------------------*/
5156 /* genSkipCond                                                     */
5157 /*-----------------------------------------------------------------*/
5158 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5159 {
5160   if(!rifx)
5161     return;
5162
5163   if(rifx->condition)
5164     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5165   else
5166     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5167
5168
5169   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5170   rifx->generated = 1;
5171 }
5172 #endif
5173
5174 #if 0
5175 /*-----------------------------------------------------------------*/
5176 /* genChkZeroes :- greater or less than comparison                 */
5177 /*     For each byte in a literal that is zero, inclusive or the   */
5178 /*     the corresponding byte in the operand with W                */
5179 /*     returns true if any of the bytes are zero                   */
5180 /*-----------------------------------------------------------------*/
5181 static int genChkZeroes(operand *op, int lit,  int size)
5182 {
5183
5184   int i;
5185   int flag =1;
5186
5187   while(size--) {
5188     i = (lit >> (size*8)) & 0xff;
5189
5190     if(i==0) {
5191       if(flag)
5192         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5193       else
5194         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5195       flag = 0;
5196     }
5197   }
5198
5199   return (flag==0);
5200 }
5201 #endif
5202
5203
5204 /*-----------------------------------------------------------------*/
5205 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5206 /*                  aop (if it's NOT a literal) or from lit (if    */
5207 /*                  aop is a literal)                              */
5208 /*-----------------------------------------------------------------*/
5209 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5210   if (aop->type == AOP_LIT) {
5211     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5212   } else {
5213     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5214   }
5215 }
5216
5217 /*-----------------------------------------------------------------*/
5218 /* genCmp :- greater or less than comparison                       */
5219 /*-----------------------------------------------------------------*/
5220
5221 #if USE_SIMPLE_GENCMP           /* { */
5222
5223 /* genCmp performs a left < right comparison, stores
5224  * the outcome in result (if != NULL) and generates
5225  * control flow code for the ifx (if != NULL).
5226  *
5227  * This version leaves in sequences like
5228  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5229  * which should be optmized by the peephole
5230  * optimizer - RN 2005-01-01 */
5231 static void genCmp (operand *left,operand *right,
5232                     operand *result, iCode *ifx, int sign)
5233 {
5234   resolvedIfx rIfx;
5235   int size;
5236   int offs;
5237   symbol *templbl;
5238   operand *dummy;
5239   unsigned long lit;
5240   unsigned long mask;
5241   int performedLt;
5242
5243   FENTRY;
5244
5245   assert (left && right);
5246   assert (AOP_SIZE(left) == AOP_SIZE(right));
5247
5248   size = AOP_SIZE(right) - 1;
5249   mask = (0x100UL << (size*8)) - 1;
5250   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5251   performedLt = 1;
5252   templbl = NULL;
5253   lit = 0;
5254
5255   resolveIfx (&rIfx, ifx);
5256
5257   /* handle for special cases */
5258   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5259       return;
5260
5261   /**********************************************************************
5262    * handle bits - bit compares are promoted to int compares seemingly! *
5263    **********************************************************************/
5264 #if 0
5265   // THIS IS COMPLETELY UNTESTED!
5266   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5267     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5268     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5269     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5270
5271     emitSETC;
5272     // 1 < {0,1} is false --> clear C by skipping the next instruction
5273     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5274     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5275     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5276     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5277     emitCLRC; // only skipped for left=0 && right=1
5278
5279     goto correct_result_in_carry;
5280   } // if
5281 #endif
5282
5283   /*************************************************
5284    * make sure that left is register (or the like) *
5285    *************************************************/
5286   if (!isAOP_REGlike(left)) {
5287     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5288     assert (isAOP_LIT(left));
5289     assert (isAOP_REGlike(right));
5290     // swap left and right
5291     // left < right <==> right > left <==> (right >= left + 1)
5292     lit = ulFromVal (AOP(left)->aopu.aop_lit);
5293
5294     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5295       // MAXVALUE < right? always false
5296       if (performedLt) emitCLRC; else emitSETC;
5297       goto correct_result_in_carry;
5298     } // if
5299
5300     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5301     // that's why we handled it above.
5302     lit++;
5303
5304     dummy = left;
5305     left = right;
5306     right = dummy;
5307
5308     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5309   } else if (isAOP_LIT(right)) {
5310     lit = ulFromVal (AOP(right)->aopu.aop_lit);
5311   } // if
5312
5313   assert (isAOP_REGlike(left)); // left must be register or the like
5314   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5315
5316   /*************************************************
5317    * special cases go here                         *
5318    *************************************************/
5319
5320   if (isAOP_LIT(right)) {
5321     if (!sign) {
5322       // unsigned comparison to a literal
5323       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5324       if (lit == 0) {
5325         // unsigned left < 0? always false
5326         if (performedLt) emitCLRC; else emitSETC;
5327         goto correct_result_in_carry;
5328       }
5329     } else {
5330       // signed comparison to a literal
5331       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5332       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5333         // signed left < 0x80000000? always false
5334         if (performedLt) emitCLRC; else emitSETC;
5335         goto correct_result_in_carry;
5336       } else if (lit == 0) {
5337         // compare left < 0; set CARRY if SIGNBIT(left) is set
5338         if (performedLt) emitSETC; else emitCLRC;
5339         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5340         if (performedLt) emitCLRC; else emitSETC;
5341         goto correct_result_in_carry;
5342       }
5343     } // if (!sign)
5344   } // right is literal
5345
5346   /*************************************************
5347    * perform a general case comparison             *
5348    * make sure we get CARRY==1 <==> left >= right  *
5349    *************************************************/
5350   // compare most significant bytes
5351   //DEBUGpc ("comparing bytes at offset %d", size);
5352   if (!sign) {
5353     // unsigned comparison
5354     mov2w_regOrLit (AOP(right), lit, size);
5355     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5356   } else {
5357     // signed comparison
5358     // (add 2^n to both operands then perform an unsigned comparison)
5359     if (isAOP_LIT(right)) {
5360       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5361       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5362
5363       if (litbyte == 0x80) {
5364         // left >= 0x80 -- always true, but more bytes to come
5365         pic16_mov2w (AOP(left), size);
5366         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5367         emitSETC;
5368       } else {
5369         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5370         pic16_mov2w (AOP(left), size);
5371         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5372         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5373       } // if
5374     } else {
5375       /* using PRODL as a temporary register here */
5376       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5377       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5378       pic16_mov2w (AOP(left), size);
5379       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5380       pic16_emitpcode (POC_MOVWF, pctemp);
5381       pic16_mov2w (AOP(right), size);
5382       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5383       pic16_emitpcode (POC_SUBFW, pctemp);
5384       //pic16_popReleaseTempReg(pctemp, 1);
5385     }
5386   } // if (!sign)
5387
5388   // compare remaining bytes (treat as unsigned case from above)
5389   templbl = newiTempLabel ( NULL );
5390   offs = size;
5391   while (offs--) {
5392     //DEBUGpc ("comparing bytes at offset %d", offs);
5393     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5394     mov2w_regOrLit (AOP(right), lit, offs);
5395     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5396   } // while (offs)
5397   pic16_emitpLabel (templbl->key);
5398   goto result_in_carry;
5399
5400 result_in_carry:
5401
5402   /****************************************************
5403    * now CARRY contains the result of the comparison: *
5404    * SUBWF sets CARRY iff                             *
5405    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5406    * (F=left, W=right)                                *
5407    ****************************************************/
5408
5409   if (performedLt) {
5410     if (result && AOP_TYPE(result) != AOP_CRY) {
5411       // value will be stored
5412       emitTOGC;
5413     } else {
5414       // value wil only be used in the following genSkipc()
5415       rIfx.condition ^= 1;
5416     }
5417   } // if
5418
5419 correct_result_in_carry:
5420
5421   // assign result to variable (if neccessary)
5422   if (result && AOP_TYPE(result) != AOP_CRY) {
5423     //DEBUGpc ("assign result");
5424     size = AOP_SIZE(result);
5425     while (size--) {
5426       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5427     } // while
5428     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5429   } // if (result)
5430
5431   // perform conditional jump
5432   if (ifx) {
5433     //DEBUGpc ("generate control flow");
5434     genSkipc (&rIfx);
5435     ifx->generated = 1;
5436   } // if
5437 }
5438
5439 #elif 1         /* } */
5440                 /* { */
5441       /* original code */
5442 static void genCmp (operand *left,operand *right,
5443                     operand *result, iCode *ifx, int sign)
5444 {
5445   int size; //, offset = 0 ;
5446   unsigned long lit = 0L,i = 0;
5447   resolvedIfx rFalseIfx;
5448   //  resolvedIfx rTrueIfx;
5449   symbol *truelbl;
5450   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5451 /*
5452   if(ifx) {
5453     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5454     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5455   }
5456 */
5457
5458   FENTRY;
5459
5460   resolveIfx(&rFalseIfx,ifx);
5461   truelbl  = newiTempLabel(NULL);
5462   size = max(AOP_SIZE(left),AOP_SIZE(right));
5463
5464   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5465
5466 #define _swapp
5467
5468   /* if literal is on the right then swap with left */
5469   if ((AOP_TYPE(right) == AOP_LIT)) {
5470     operand *tmp = right ;
5471     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5472     lit = ulFromVal (AOP(right)->aopu.aop_lit);
5473 #ifdef _swapp
5474
5475     lit = (lit - 1) & mask;
5476     right = left;
5477     left = tmp;
5478     rFalseIfx.condition ^= 1;
5479 #endif
5480
5481   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5482     lit = ulFromVal (AOP(left)->aopu.aop_lit);
5483   }
5484
5485
5486   //if(IC_TRUE(ifx) == NULL)
5487   /* if left & right are bit variables */
5488   if (AOP_TYPE(left) == AOP_CRY &&
5489       AOP_TYPE(right) == AOP_CRY ) {
5490     assert (0 && "bit variables used in genCmp");
5491     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5492     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5493   } else {
5494     /* subtract right from left if at the
5495        end the carry flag is set then we know that
5496        left is greater than right */
5497
5498     symbol *lbl  = newiTempLabel(NULL);
5499
5500 #if 0
5501         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5502                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5503 #endif
5504
5505 #ifndef _swapp
5506     if(AOP_TYPE(right) == AOP_LIT) {
5507
5508       //lit = ulFromVal (AOP(right)->aopu.aop_lit);
5509
5510       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5511
5512       /* special cases */
5513
5514       if(lit == 0) {
5515
5516         if(sign != 0)
5517           genSkipCond(&rFalseIfx,left,size-1,7);
5518         else
5519           /* no need to compare to 0...*/
5520           /* NOTE: this is a de-generate compare that most certainly
5521            *       creates some dead code. */
5522           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5523
5524         if(ifx) ifx->generated = 1;
5525         return;
5526
5527       }
5528       size--;
5529
5530       if(size == 0) {
5531         //i = (lit >> (size*8)) & 0xff;
5532         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5533
5534         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5535
5536         i = ((0-lit) & 0xff);
5537         if(sign) {
5538           if( i == 0x81) {
5539             /* lit is 0x7f, all signed chars are less than
5540              * this except for 0x7f itself */
5541             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5542             genSkipz2(&rFalseIfx,0);
5543           } else {
5544             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5545             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5546             genSkipc(&rFalseIfx);
5547           }
5548
5549         } else {
5550           if(lit == 1) {
5551             genSkipz2(&rFalseIfx,1);
5552           } else {
5553             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5554             genSkipc(&rFalseIfx);
5555           }
5556         }
5557
5558         if(ifx) ifx->generated = 1;
5559         return;
5560       }
5561
5562       /* chars are out of the way. now do ints and longs */
5563
5564
5565       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5566
5567       /* special cases */
5568
5569       if(sign) {
5570
5571         if(lit == 0) {
5572           genSkipCond(&rFalseIfx,left,size,7);
5573           if(ifx) ifx->generated = 1;
5574           return;
5575         }
5576
5577         if(lit <0x100) {
5578           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5579
5580           //rFalseIfx.condition ^= 1;
5581           //genSkipCond(&rFalseIfx,left,size,7);
5582           //rFalseIfx.condition ^= 1;
5583
5584           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5585           if(rFalseIfx.condition)
5586             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5587           else
5588             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5589
5590           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5591           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5592           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5593
5594           while(size > 1)
5595             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5596
5597           if(rFalseIfx.condition) {
5598             emitSKPZ;
5599             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5600
5601           } else {
5602             emitSKPNZ;
5603           }
5604
5605           genSkipc(&rFalseIfx);
5606           pic16_emitpLabel(truelbl->key);
5607           if(ifx) ifx->generated = 1;
5608           return;
5609
5610         }
5611
5612         if(size == 1) {
5613
5614           if( (lit & 0xff) == 0) {
5615             /* lower byte is zero */
5616             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5617             i = ((lit >> 8) & 0xff) ^0x80;
5618             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5619             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5620             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5621             genSkipc(&rFalseIfx);
5622
5623
5624             if(ifx) ifx->generated = 1;
5625             return;
5626
5627           }
5628         } else {
5629           /* Special cases for signed longs */
5630           if( (lit & 0xffffff) == 0) {
5631             /* lower byte is zero */
5632             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5633             i = ((lit >> 8*3) & 0xff) ^0x80;
5634             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5635             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5636             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5637             genSkipc(&rFalseIfx);
5638
5639
5640             if(ifx) ifx->generated = 1;
5641             return;
5642
5643           }
5644
5645         }
5646
5647
5648         if(lit & (0x80 << (size*8))) {
5649           /* lit is negative */
5650           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5651
5652           //genSkipCond(&rFalseIfx,left,size,7);
5653
5654           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5655
5656           if(rFalseIfx.condition)
5657             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5658           else
5659             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5660
5661
5662         } else {
5663           /* lit is positive */
5664           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5665           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5666           if(rFalseIfx.condition)
5667             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5668           else
5669             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5670
5671         }
5672
5673         /*
5674           This works, but is only good for ints.
5675           It also requires a "known zero" register.
5676           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5677           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5678           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5679           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5680           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5681           genSkipc(&rFalseIfx);
5682
5683           pic16_emitpLabel(truelbl->key);
5684           if(ifx) ifx->generated = 1;
5685           return;
5686         **/
5687
5688         /* There are no more special cases, so perform a general compare */
5689
5690         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5691         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5692
5693         while(size--) {
5694
5695           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5696           emitSKPNZ;
5697           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5698         }
5699         //rFalseIfx.condition ^= 1;
5700         genSkipc(&rFalseIfx);
5701
5702         pic16_emitpLabel(truelbl->key);
5703
5704         if(ifx) ifx->generated = 1;
5705         return;
5706
5707
5708       }
5709
5710
5711       /* sign is out of the way. So now do an unsigned compare */
5712       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5713
5714
5715       /* General case - compare to an unsigned literal on the right.*/
5716
5717       i = (lit >> (size*8)) & 0xff;
5718       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5719       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5720       while(size--) {
5721         i = (lit >> (size*8)) & 0xff;
5722
5723         if(i) {
5724           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5725           emitSKPNZ;
5726           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5727         } else {
5728           /* this byte of the lit is zero,
5729            *if it's not the last then OR in the variable */
5730           if(size)
5731             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5732         }
5733       }
5734
5735
5736       pic16_emitpLabel(lbl->key);
5737 //      pic16_emitpLabel(truelbl->key);
5738       //if(emitFinalCheck)
5739       genSkipc(&rFalseIfx);
5740       if(sign)
5741         pic16_emitpLabel(truelbl->key);
5742
5743       if(ifx) ifx->generated = 1;
5744       return;
5745
5746
5747     }
5748 #endif  // _swapp
5749
5750     if(AOP_TYPE(left) == AOP_LIT) {
5751       //symbol *lbl = newiTempLabel(NULL);
5752
5753       //EXPERIMENTAL lit = ulFromVal (AOP(left)->aopu.aop_lit);
5754
5755
5756       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5757
5758       /* Special cases */
5759       if((lit == 0) && (sign == 0)){
5760
5761         size--;
5762         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5763         while(size)
5764           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5765
5766         genSkipz2(&rFalseIfx,0);
5767         if(ifx) ifx->generated = 1;
5768         return;
5769       }
5770
5771       if(size==1) {
5772         /* Special cases */
5773         lit &= 0xff;
5774         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5775           /* degenerate compare can never be true */
5776           if(rFalseIfx.condition == 0)
5777             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5778
5779           if(ifx) ifx->generated = 1;
5780           return;
5781         }
5782
5783         if(sign) {
5784           /* signed comparisons to a literal byte */
5785
5786           int lp1 = (lit+1) & 0xff;
5787
5788           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5789           switch (lp1) {
5790           case 0:
5791             rFalseIfx.condition ^= 1;
5792             genSkipCond(&rFalseIfx,right,0,7);
5793             break;
5794           case 0x7f:
5795             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5796             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5797             genSkipz2(&rFalseIfx,1);
5798             break;
5799           default:
5800             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5801             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5802             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5803             rFalseIfx.condition ^= 1;
5804             genSkipc(&rFalseIfx);
5805             break;
5806           }
5807         } else {
5808           /* unsigned comparisons to a literal byte */
5809
5810           switch(lit & 0xff ) {
5811           case 0:
5812             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5813             genSkipz2(&rFalseIfx,0);
5814             break;
5815           case 0x7f:
5816             rFalseIfx.condition ^= 1;
5817             genSkipCond(&rFalseIfx,right,0,7);
5818             break;
5819
5820           default:
5821             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5822             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5823             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824             rFalseIfx.condition ^= 1;
5825             if (AOP_TYPE(result) == AOP_CRY)
5826               genSkipc(&rFalseIfx);
5827             else {
5828               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5829               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5830             }
5831             break;
5832           }
5833         }
5834
5835         if(ifx) ifx->generated = 1;
5836         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5837                 goto check_carry;
5838         return;
5839
5840       } else {
5841
5842         /* Size is greater than 1 */
5843
5844         if(sign) {
5845           int lp1 = lit+1;
5846
5847           size--;
5848
5849           if(lp1 == 0) {
5850             /* this means lit = 0xffffffff, or -1 */
5851
5852
5853             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5854             rFalseIfx.condition ^= 1;
5855             genSkipCond(&rFalseIfx,right,size,7);
5856             if(ifx) ifx->generated = 1;
5857
5858             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5859               goto check_carry;
5860
5861             return;
5862           }
5863
5864           if(lit == 0) {
5865             int s = size;
5866
5867             if(rFalseIfx.condition) {
5868               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5869               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5870             }
5871
5872             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5873             while(size--)
5874               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5875
5876
5877             emitSKPZ;
5878             if(rFalseIfx.condition) {
5879               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5880               pic16_emitpLabel(truelbl->key);
5881             }else {
5882               rFalseIfx.condition ^= 1;
5883               genSkipCond(&rFalseIfx,right,s,7);
5884             }
5885
5886             if(ifx) ifx->generated = 1;
5887
5888             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889               goto check_carry;
5890
5891             return;
5892           }
5893
5894           if((size == 1) &&  (0 == (lp1&0xff))) {
5895             /* lower byte of signed word is zero */
5896             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5897             i = ((lp1 >> 8) & 0xff) ^0x80;
5898             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5899             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5900             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5901
5902             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5903               emitTOGC;
5904               if(ifx) ifx->generated = 1;
5905               goto check_carry;
5906             } else {
5907               rFalseIfx.condition ^= 1;
5908               genSkipc(&rFalseIfx);
5909               if(ifx) ifx->generated = 1;
5910             }
5911
5912             return;
5913           }
5914
5915           if(lit & (0x80 << (size*8))) {
5916             /* Lit is less than zero */
5917             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5918             //rFalseIfx.condition ^= 1;
5919             //genSkipCond(&rFalseIfx,left,size,7);
5920             //rFalseIfx.condition ^= 1;
5921             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5922             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5923
5924             if(rFalseIfx.condition)
5925               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5926             else
5927               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5928
5929
5930           } else {
5931             /* Lit is greater than or equal to zero */
5932             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5933             //rFalseIfx.condition ^= 1;
5934             //genSkipCond(&rFalseIfx,right,size,7);
5935             //rFalseIfx.condition ^= 1;
5936
5937             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5938             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5939
5940             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5941             if(rFalseIfx.condition)
5942               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5943             else
5944               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5945
5946           }
5947
5948           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5949           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5950
5951           while(size--) {
5952
5953             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5954             emitSKPNZ;
5955             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5956           }
5957           rFalseIfx.condition ^= 1;
5958           //rFalseIfx.condition = 1;
5959           genSkipc(&rFalseIfx);
5960
5961           pic16_emitpLabel(truelbl->key);
5962
5963           if(ifx) ifx->generated = 1;
5964
5965
5966           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5967             goto check_carry;
5968
5969           return;
5970           // end of if (sign)
5971         } else {
5972
5973           /* compare word or long to an unsigned literal on the right.*/
5974
5975
5976           size--;
5977           if(lit < 0xff) {
5978             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5979             switch (lit) {
5980             case 0:
5981               break; /* handled above */
5982 /*
5983             case 0xff:
5984               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5985               while(size--)
5986                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5987               genSkipz2(&rFalseIfx,0);
5988               break;
5989 */
5990             default:
5991               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5992               while(--size)
5993                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5994
5995               emitSKPZ;
5996               if(rFalseIfx.condition)
5997                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5998               else
5999                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6000
6001
6002               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6003               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6004
6005               rFalseIfx.condition ^= 1;
6006               genSkipc(&rFalseIfx);
6007             }
6008
6009             pic16_emitpLabel(truelbl->key);
6010
6011             if(ifx) ifx->generated = 1;
6012
6013             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6014               goto check_carry;
6015
6016             return;
6017           }
6018
6019
6020           lit++;
6021           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6022           i = (lit >> (size*8)) & 0xff;
6023
6024           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6025           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6026
6027           while(size--) {
6028             i = (lit >> (size*8)) & 0xff;
6029
6030             if(i) {
6031               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6032               emitSKPNZ;
6033               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6034             } else {
6035               /* this byte of the lit is zero,
6036                * if it's not the last then OR in the variable */
6037               if(size)
6038                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6039             }
6040           }
6041
6042
6043           pic16_emitpLabel(lbl->key);
6044
6045           rFalseIfx.condition ^= 1;
6046
6047           genSkipc(&rFalseIfx);
6048         }
6049
6050         if(sign)
6051           pic16_emitpLabel(truelbl->key);
6052         if(ifx) ifx->generated = 1;
6053
6054             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6055               goto check_carry;
6056
6057         return;
6058       }
6059     }
6060     /* Compare two variables */
6061
6062     DEBUGpic16_emitcode(";sign","%d",sign);
6063
6064     size--;
6065     if(sign) {
6066       /* Sigh. thus sucks... */
6067       if(size) {
6068         pCodeOp *pctemp;
6069
6070         pctemp = pic16_popGetTempReg(1);
6071         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6072         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6073         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6074         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6075         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6076         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6077         pic16_popReleaseTempReg(pctemp, 1);
6078       } else {
6079         /* Signed char comparison */
6080         /* Special thanks to Nikolai Golovchenko for this snippet */
6081         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6082         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6083         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6084         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6085         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6086         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6087
6088         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6089         genSkipc(&rFalseIfx);
6090
6091         if(ifx) ifx->generated = 1;
6092
6093             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6094               goto check_carry;
6095
6096         return;
6097       }
6098
6099     } else {
6100
6101       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6102       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6103     }
6104
6105
6106     /* The rest of the bytes of a multi-byte compare */
6107     while (size) {
6108
6109       emitSKPZ;
6110       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6111       size--;
6112
6113       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6114       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6115
6116
6117     }
6118
6119     pic16_emitpLabel(lbl->key);
6120
6121     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6122     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) ||
6123         (AOP_TYPE(result) == AOP_REG)) {
6124       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6125       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6126     } else {
6127       genSkipc(&rFalseIfx);
6128     }
6129     //genSkipc(&rFalseIfx);
6130     if(ifx) ifx->generated = 1;
6131
6132
6133             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6134               goto check_carry;
6135
6136     return;
6137
6138   }
6139
6140 check_carry:
6141   if ((AOP_TYPE(result) != AOP_CRY)
6142         && AOP_SIZE(result)) {
6143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6144
6145     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6146
6147     pic16_outBitC(result);
6148   } else {
6149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6150     /* if the result is used in the next
6151        ifx conditional branch then generate
6152        code a little differently */
6153     if (ifx )
6154       genIfxJump (ifx,"c");
6155     else
6156       pic16_outBitC(result);
6157     /* leave the result in acc */
6158   }
6159
6160 }
6161
6162 #elif 0 /* VR version of genCmp() */    /* } else { */
6163
6164 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6165 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6166         operand *result, int offset, int invert_op)
6167 {
6168   /* add code here */
6169
6170   /* check condition, > or < ?? */
6171   if(rIfx->condition != 0)invert_op ^= 1;
6172
6173   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6174
6175   if(!ifx)invert_op ^= 1;
6176
6177   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6178       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6179
6180   /* do selection */
6181   if(!invert_op)return POC_CPFSGT;
6182   else return POC_CPFSLT;
6183 }
6184
6185 static int compareAopfirstpass=1;
6186
6187 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6188             operand *oper, int offset, operand *result,
6189             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6190             symbol *tlbl)
6191 {
6192   int op;
6193   symbol *truelbl;
6194
6195   /* invert if there is a result to be loaded, in order to fit,
6196    * SETC/CLRC sequence */
6197   if(AOP_SIZE(result))invert_op ^= 1;
6198
6199 //  if(sign && !offset)invert_op ^= 1;
6200
6201 //  if(sign)invert_op ^= 1;
6202
6203   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6204
6205   if(AOP_SIZE(result) && compareAopfirstpass) {
6206     if(!ifx) {
6207       if(pcop2)
6208         pic16_emitpcode(POC_SETF, pcop2);
6209       else
6210         emitSETC;
6211     } else {
6212       if(pcop2)
6213         pic16_emitpcode(POC_CLRF, pcop2);
6214       else
6215         emitCLRC;
6216     }
6217   }
6218
6219   compareAopfirstpass = 0;
6220
6221       /* there is a bug when comparing operands with size > 1,
6222        * because higher bytes can be equal and test should be performed
6223        * to the next lower byte, current algorithm, considers operands
6224        * inequal in these cases! -- VR 20041107 */
6225
6226
6227   if(pcop)
6228     pic16_emitpcode(op, pcop);
6229   else
6230     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6231
6232
6233   if((!sign || !offset) && AOP_SIZE(result)) {
6234     if(!ifx) {
6235       if(pcop2)
6236         pic16_emitpcode(POC_CLRF, pcop2);
6237         else
6238         emitCLRC;
6239     } else {
6240       if(pcop2)
6241         pic16_emitpcode(POC_SETF, pcop2);
6242       else
6243         emitSETC;
6244     }
6245
6246     /* don't emit final branch (offset == 0) */
6247     if(offset) {
6248
6249       if(pcop2)
6250         pic16_emitpcode(POC_RRCF, pcop2);
6251
6252       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6253     }
6254   } else {
6255     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6256       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6257             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6258
6259       truelbl = newiTempLabel( NULL );
6260       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6261       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6262         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6263       else
6264         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6265       pic16_emitpLabel(truelbl->key);
6266     } else {
6267       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6268     }
6269   }
6270 }
6271
6272 static void genCmp (operand *left, operand *right,
6273                     operand *result, iCode *ifx, int sign)
6274 {
6275   int size, cmpop=1;
6276   long lit = 0L;
6277   resolvedIfx rFalseIfx;
6278   symbol *falselbl, *tlbl;
6279
6280     FENTRY;
6281
6282     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6283
6284     resolveIfx(&rFalseIfx, ifx);
6285     size = max(AOP_SIZE(left), AOP_SIZE(right));
6286
6287     /* if left & right are bit variables */
6288     if(AOP_TYPE(left) == AOP_CRY
6289       && AOP_TYPE(right) == AOP_CRY ) {
6290
6291         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6292         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6293
6294         werror(W_POSSBUG2, __FILE__, __LINE__);
6295         exit(EXIT_FAILURE);
6296     }
6297
6298     /* if literal is on the right then swap with left */
6299     if((AOP_TYPE(right) == AOP_LIT)) {
6300       operand *tmp = right ;
6301 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6302
6303         lit = ulFromVal (AOP(right)->aopu.aop_lit);
6304
6305 //      lit = (lit - 1) & mask;
6306         right = left;
6307         left = tmp;
6308         rFalseIfx.condition ^= 1;               /* reverse compare */
6309     } else
6310     if ((AOP_TYPE(left) == AOP_LIT)) {
6311       /* float compares are handled by support functions */
6312       lit = ulFromVal(AOP(left)->aopu.aop_lit);
6313     }
6314
6315     /* actual comparing algorithm */
6316 //    size = AOP_SIZE( right );
6317
6318     falselbl = newiTempLabel( NULL );
6319     if(AOP_TYPE(left) == AOP_LIT) {
6320       /* compare to literal */
6321       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6322
6323       if(sign) {
6324         pCodeOp *pct, *pct2;
6325         symbol *tlbl1;
6326
6327         /* signed compare */
6328         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6329
6330         /* using PRODL:PRODH as a temporary register here */
6331         pct = pic16_popCopyReg(&pic16_pc_prodl);
6332         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6333         tlbl = newiTempLabel( NULL );
6334
6335         /* first compare signs:
6336          *  a. if both are positive, compare just like unsigned
6337          *  b. if both are negative, invert cmpop, compare just like unsigned
6338          *  c. if different signs, determine the result directly */
6339
6340         size--;
6341
6342 #if 1
6343         /* { */
6344         tlbl1 = newiTempLabel( NULL );
6345 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6346
6347         if(lit > 0) {
6348
6349           /* literal is zero or positive:
6350            *  a. if carry is zero, too, continue compare,
6351            *  b. if carry is set, then continue depending on cmpop ^ condition:
6352            *    1. '<' return false (literal < variable),
6353            *    2. '>' return true (literal > variable) */
6354 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6355           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6356
6357
6358           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6359           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6360         } else
6361         if(lit < 0) {
6362
6363           /* literal is negative:
6364            *  a. if carry is set, too, continue compare,
6365            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6366            *    1. '<' return true (literal < variable),
6367            *    2. '>' return false (literal > variable) */
6368 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6369           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6370
6371           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6372           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6373         }
6374 #if 1
6375         else {
6376           /* lit == 0 */
6377           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6378
6379           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6380           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6381         }
6382 #endif
6383
6384
6385         pic16_emitpLabel( tlbl1->key );
6386 #endif  /* } */
6387
6388         compareAopfirstpass=1;
6389 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6390 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6391 //        pic16_emitpcode(POC_MOVWF, pct);
6392
6393 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6394         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6395 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6396         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6397
6398         /* generic case */
6399           while( size-- ) {
6400 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6401 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6402 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6403 //            pic16_emitpcode(POC_MOVWF, pct);
6404
6405 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6406             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6407             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6408 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6409 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6410           }
6411
6412         if(ifx)ifx->generated = 1;
6413
6414         if(AOP_SIZE(result)) {
6415           pic16_emitpLabel(tlbl->key);
6416           pic16_emitpLabel(falselbl->key);
6417           pic16_outBitOp( result, pct2 );
6418         } else {
6419           pic16_emitpLabel(tlbl->key);
6420         }
6421       } else {
6422
6423         /* unsigned compare */
6424         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6425
6426         compareAopfirstpass=1;
6427         while(size--) {
6428
6429           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6430           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6431
6432         }
6433         if(ifx)ifx->generated = 1;
6434
6435         if(AOP_SIZE(result)) {
6436           pic16_emitpLabel(falselbl->key);
6437           pic16_outBitC( result );
6438         }
6439
6440       }
6441     } else {
6442       /* compare registers */
6443       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6444
6445
6446       if(sign) {
6447         pCodeOp *pct, *pct2;
6448
6449         /* signed compare */
6450         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6451
6452         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6453         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6454         tlbl = newiTempLabel( NULL );
6455
6456         compareAopfirstpass=1;
6457
6458         size--;
6459         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6460 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6461         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6462         pic16_emitpcode(POC_MOVWF, pct);
6463
6464         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6465 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6467
6468         /* WREG already holds left + 0x80 */
6469         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6470
6471         while( size-- ) {
6472           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6473 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6474           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6475           pic16_emitpcode(POC_MOVWF, pct);
6476
6477           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6478 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6479           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6480
6481           /* WREG already holds left + 0x80 */
6482           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6483 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6484         }
6485
6486         if(ifx)ifx->generated = 1;
6487
6488         if(AOP_SIZE(result)) {
6489           pic16_emitpLabel(tlbl->key);
6490           pic16_emitpLabel(falselbl->key);
6491           pic16_outBitOp( result, pct2 );
6492         } else {
6493           pic16_emitpLabel(tlbl->key);
6494         }
6495
6496       } else {
6497         /* unsigned compare */
6498         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6499
6500         compareAopfirstpass=1;
6501         while(size--) {
6502
6503           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6504           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6505
6506         }
6507
6508         if(ifx)ifx->generated = 1;
6509         if(AOP_SIZE(result)) {
6510
6511           pic16_emitpLabel(falselbl->key);
6512           pic16_outBitC( result );
6513         }
6514
6515       }
6516     }
6517 }
6518
6519 #endif  /* } */
6520
6521
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genCmpGt :- greater than comparison                             */
6525 /*-----------------------------------------------------------------*/
6526 static void genCmpGt (iCode *ic, iCode *ifx)
6527 {
6528   operand *left, *right, *result;
6529   sym_link *letype , *retype;
6530   int sign ;
6531
6532     FENTRY;
6533
6534     left = IC_LEFT(ic);
6535     right= IC_RIGHT(ic);
6536     result = IC_RESULT(ic);
6537
6538     letype = getSpec(operandType(left));
6539     retype =getSpec(operandType(right));
6540     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6541     /* assign the amsops */
6542     pic16_aopOp (left,ic,FALSE);
6543     pic16_aopOp (right,ic,FALSE);
6544     pic16_aopOp (result,ic,TRUE);
6545
6546     genCmp(right, left, result, ifx, sign);
6547
6548     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6550     pic16_freeAsmop(result,NULL,ic,TRUE);
6551 }
6552
6553 /*-----------------------------------------------------------------*/
6554 /* genCmpLt - less than comparisons                                */
6555 /*-----------------------------------------------------------------*/
6556 static void genCmpLt (iCode *ic, iCode *ifx)
6557 {
6558   operand *left, *right, *result;
6559   sym_link *letype , *retype;
6560   int sign ;
6561
6562     FENTRY;
6563
6564     left = IC_LEFT(ic);
6565     right= IC_RIGHT(ic);
6566     result = IC_RESULT(ic);
6567
6568     letype = getSpec(operandType(left));
6569     retype =getSpec(operandType(right));
6570     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6571
6572     /* assign the amsops */
6573     pic16_aopOp (left,ic,FALSE);
6574     pic16_aopOp (right,ic,FALSE);
6575     pic16_aopOp (result,ic,TRUE);
6576
6577     genCmp(left, right, result, ifx, sign);
6578
6579     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6581     pic16_freeAsmop(result,NULL,ic,TRUE);
6582 }
6583
6584 #if 0
6585 // not needed ATM
6586 // FIXME reenable literal optimisation when the pic16 port is stable
6587
6588 /*-----------------------------------------------------------------*/
6589 /* genc16bit2lit - compare a 16 bit value to a literal             */
6590 /*-----------------------------------------------------------------*/
6591 static void genc16bit2lit(operand *op, int lit, int offset)
6592 {
6593   int i;
6594
6595   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6596   if( (lit&0xff) == 0)
6597     i=1;
6598   else
6599     i=0;
6600
6601   switch( BYTEofLONG(lit,i)) {
6602   case 0:
6603     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6604     break;
6605   case 1:
6606     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6607     break;
6608   case 0xff:
6609     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6610     break;
6611   default:
6612     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6613     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6614   }
6615
6616   i ^= 1;
6617
6618   switch( BYTEofLONG(lit,i)) {
6619   case 0:
6620     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6621     break;
6622   case 1:
6623     emitSKPNZ;
6624     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6625     break;
6626   case 0xff:
6627     emitSKPNZ;
6628     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6629     break;
6630   default:
6631     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6632     emitSKPNZ;
6633     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6634
6635   }
6636
6637 }
6638 #endif
6639
6640 #if 0
6641 // not needed ATM
6642 /*-----------------------------------------------------------------*/
6643 /* gencjneshort - compare and jump if not equal                    */
6644 /*-----------------------------------------------------------------*/
6645 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6646 {
6647   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6648   int offset = 0;
6649   int res_offset = 0;  /* the result may be a different size then left or right */
6650   int res_size = AOP_SIZE(result);
6651   resolvedIfx rIfx;
6652   symbol *lbl, *lbl_done;
6653
6654   unsigned long lit = 0L;
6655   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6656
6657   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6658   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6659   if(result)
6660     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6661   resolveIfx(&rIfx,ifx);
6662   lbl =  newiTempLabel(NULL);
6663   lbl_done =  newiTempLabel(NULL);
6664
6665
6666   /* if the left side is a literal or
6667      if the right is in a pointer register and left
6668      is not */
6669   if ((AOP_TYPE(left) == AOP_LIT) ||
6670       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6671     operand *t = right;
6672     right = left;
6673     left = t;
6674   }
6675   if(AOP_TYPE(right) == AOP_LIT)
6676     lit = ulFromVal (AOP(right)->aopu.aop_lit);
6677
6678   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6679     preserve_result = 1;
6680
6681   if(result && !preserve_result)
6682     {
6683       int i;
6684       for(i = 0; i < AOP_SIZE(result); i++)
6685         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6686     }
6687
6688
6689   /* if the right side is a literal then anything goes */
6690   if (AOP_TYPE(right) == AOP_LIT &&
6691       AOP_TYPE(left) != AOP_DIR ) {
6692     switch(size) {
6693     case 2:
6694       genc16bit2lit(left, lit, 0);
6695       emitSKPZ;
6696       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6697       break;
6698     default:
6699       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6700       while (size--) {
6701         if(lit & 0xff) {
6702           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6703           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6704         } else {
6705           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6706         }
6707
6708         emitSKPZ;
6709         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6710         offset++;
6711         if(res_offset < res_size-1)
6712           res_offset++;
6713         lit >>= 8;
6714       }
6715       break;
6716     }
6717   }
6718
6719   /* if the right side is in a register or in direct space or
6720      if the left is a pointer register & right is not */
6721   else if (AOP_TYPE(right) == AOP_REG ||
6722            AOP_TYPE(right) == AOP_DIR ||
6723            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6724            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6725     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6726     int lbl_key = lbl->key;
6727
6728     if(result) {
6729       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6730       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6731     }else {
6732       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6733       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6734               __FUNCTION__,__LINE__);
6735       return;
6736     }
6737
6738 /*     switch(size) { */
6739 /*     case 2: */
6740 /*       genc16bit2lit(left, lit, 0); */
6741 /*       emitSKPNZ; */
6742 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6743 /*       break; */
6744 /*     default: */
6745     while (size--) {
6746       int emit_skip=1;
6747       if((AOP_TYPE(left) == AOP_DIR) &&
6748          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6749
6750         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6751         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6752
6753       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6754
6755         switch (lit & 0xff) {
6756         case 0:
6757           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6758           break;
6759         case 1:
6760           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6761           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6762           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6763           emit_skip=0;
6764           break;
6765         case 0xff:
6766           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6767           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6768           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6769           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6770           emit_skip=0;
6771           break;
6772         default:
6773           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6774           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6775         }
6776         lit >>= 8;
6777
6778       } else {
6779         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6780       }
6781       if(emit_skip) {
6782         if(AOP_TYPE(result) == AOP_CRY) {
6783           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6784           if(rIfx.condition)
6785             emitSKPNZ;
6786           else
6787             emitSKPZ;
6788           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6789         } else {
6790           /* fix me. probably need to check result size too */
6791           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6792           if(rIfx.condition)
6793             emitSKPZ;
6794           else
6795             emitSKPNZ;
6796           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6797           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6798         }
6799         if(ifx)
6800           ifx->generated=1;
6801       }
6802       emit_skip++;
6803       offset++;
6804       if(res_offset < res_size-1)
6805         res_offset++;
6806     }
6807 /*       break; */
6808 /*     } */
6809   } else if(AOP_TYPE(right) == AOP_REG &&
6810             AOP_TYPE(left) != AOP_DIR){
6811
6812     while(size--) {
6813       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6814       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6815       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6816       if(rIfx.condition)
6817         emitSKPNZ;
6818       else
6819         emitSKPZ;
6820       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6821       offset++;
6822       if(res_offset < res_size-1)
6823         res_offset++;
6824     }
6825
6826   }else{
6827     /* right is a pointer reg need both a & b */
6828     while(size--) {
6829       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6830       if(strcmp(l,"b"))
6831         pic16_emitcode("mov","b,%s",l);
6832       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6833       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
6834       offset++;
6835     }
6836   }
6837
6838   if(result && preserve_result)
6839     {
6840       int i;
6841       for(i = 0; i < AOP_SIZE(result); i++)
6842         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6843     }
6844
6845   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6846
6847   if(result && preserve_result)
6848     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6849
6850   if(!rIfx.condition)
6851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6852
6853   pic16_emitpLabel(lbl->key);
6854
6855   if(result && preserve_result)
6856     {
6857       int i;
6858       for(i = 0; i < AOP_SIZE(result); i++)
6859         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6860
6861       pic16_emitpLabel(lbl_done->key);
6862    }
6863
6864   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6865
6866   if(ifx)
6867     ifx->generated = 1;
6868 }
6869 #endif
6870
6871 #if 0
6872 /*-----------------------------------------------------------------*/
6873 /* gencjne - compare and jump if not equal                         */
6874 /*-----------------------------------------------------------------*/
6875 static void gencjne(operand *left, operand *right, iCode *ifx)
6876 {
6877     symbol *tlbl  = newiTempLabel(NULL);
6878
6879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6880     gencjneshort(left, right, lbl);
6881
6882     pic16_emitcode("mov","a,%s",one);
6883     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6884     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6885     pic16_emitcode("clr","a");
6886     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6887
6888     pic16_emitpLabel(lbl->key);
6889     pic16_emitpLabel(tlbl->key);
6890
6891 }
6892 #endif
6893
6894
6895 /*-----------------------------------------------------------------*/
6896 /* is_LitOp - check if operand has to be treated as literal        */
6897 /*-----------------------------------------------------------------*/
6898 static bool is_LitOp(operand *op)
6899 {
6900   return ((AOP_TYPE(op) == AOP_LIT)
6901       || ( (AOP_TYPE(op) == AOP_PCODE)
6902           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6903               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6904 }
6905
6906 /*-----------------------------------------------------------------*/
6907 /* is_LitAOp - check if operand has to be treated as literal        */
6908 /*-----------------------------------------------------------------*/
6909 static bool is_LitAOp(asmop *aop)
6910 {
6911   return ((aop->type == AOP_LIT)
6912       || ( (aop->type == AOP_PCODE)
6913           && ( (aop->aopu.pcop->type == PO_LITERAL)
6914               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6915 }
6916
6917
6918
6919 /*-----------------------------------------------------------------*/
6920 /* genCmpEq - generates code for equal to                          */
6921 /*-----------------------------------------------------------------*/
6922 static void genCmpEq (iCode *ic, iCode *ifx)
6923 {
6924   operand *left, *right, *result;
6925   symbol *falselbl = newiTempLabel(NULL);
6926   symbol *donelbl = newiTempLabel(NULL);
6927
6928   int preserve_result = 0;
6929   int generate_result = 0;
6930   int i=0;
6931   unsigned long lit = -1;
6932
6933   FENTRY;
6934
6935   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6936   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6937   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6938
6939   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6940
6941   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6942     {
6943       werror(W_POSSBUG2, __FILE__, __LINE__);
6944       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6945       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6946       goto release;
6947     }
6948
6949   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6950     {
6951       operand *tmp = right ;
6952       right = left;
6953       left = tmp;
6954     }
6955
6956   if (AOP_TYPE(right) == AOP_LIT) {
6957     lit = ulFromVal (AOP(right)->aopu.aop_lit);
6958   }
6959
6960   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6961     preserve_result = 1;
6962
6963   if(result && AOP_SIZE(result))
6964     generate_result = 1;
6965
6966   if(generate_result && !preserve_result)
6967     {
6968       for(i = 0; i < AOP_SIZE(result); i++)
6969         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6970     }
6971
6972   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6973   for(i=0; i < AOP_SIZE(left); i++)
6974     {
6975       if(AOP_TYPE(left) != AOP_ACC)
6976         {
6977           if(is_LitOp(left))
6978             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6979           else
6980             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6981         }
6982       if(is_LitOp(right)) {
6983         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6984           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
6985         }
6986       } else
6987         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
6988
6989       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6990     }
6991
6992   // result == true
6993
6994   if(generate_result && preserve_result)
6995     {
6996       for(i = 0; i < AOP_SIZE(result); i++)
6997         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6998     }
6999
7000   if(generate_result)
7001     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7002
7003   if(generate_result && preserve_result)
7004     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7005
7006   if(ifx && IC_TRUE(ifx))
7007     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7008
7009   if(ifx && IC_FALSE(ifx))
7010     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7011
7012   pic16_emitpLabel(falselbl->key);
7013
7014   // result == false
7015
7016   if(ifx && IC_FALSE(ifx))
7017     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7018
7019   if(generate_result && preserve_result)
7020     {
7021       for(i = 0; i < AOP_SIZE(result); i++)
7022         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7023     }
7024
7025   pic16_emitpLabel(donelbl->key);
7026
7027   if(ifx)
7028     ifx->generated = 1;
7029
7030 release:
7031   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7033   pic16_freeAsmop(result,NULL,ic,TRUE);
7034
7035 }
7036
7037
7038 #if 0
7039 // old version kept for reference
7040
7041 /*-----------------------------------------------------------------*/
7042 /* genCmpEq - generates code for equal to                          */
7043 /*-----------------------------------------------------------------*/
7044 static void genCmpEq (iCode *ic, iCode *ifx)
7045 {
7046     operand *left, *right, *result;
7047     unsigned long lit = 0L;
7048     int size,offset=0;
7049     symbol *falselbl  = newiTempLabel(NULL);
7050
7051
7052     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7053
7054     if(ifx)
7055       DEBUGpic16_emitcode ("; ifx is non-null","");
7056     else
7057       DEBUGpic16_emitcode ("; ifx is null","");
7058
7059     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7060     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7061     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7062
7063     size = max(AOP_SIZE(left),AOP_SIZE(right));
7064
7065     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7066
7067     /* if literal, literal on the right or
7068     if the right is in a pointer register and left
7069     is not */
7070     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
7071         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7072       operand *tmp = right ;
7073       right = left;
7074       left = tmp;
7075     }
7076
7077
7078     if(ifx && !AOP_SIZE(result)){
7079         symbol *tlbl;
7080         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7081         /* if they are both bit variables */
7082         if (AOP_TYPE(left) == AOP_CRY &&
7083             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7084                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7085             if(AOP_TYPE(right) == AOP_LIT){
7086                 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
7087                 if(lit == 0L){
7088                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7089                     pic16_emitcode("cpl","c");
7090                 } else if(lit == 1L) {
7091                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092                 } else {
7093                     pic16_emitcode("clr","c");
7094                 }
7095                 /* AOP_TYPE(right) == AOP_CRY */
7096             } else {
7097                 symbol *lbl = newiTempLabel(NULL);
7098                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7099                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7100                 pic16_emitcode("cpl","c");
7101                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7102             }
7103             /* if true label then we jump if condition
7104             supplied is true */
7105             tlbl = newiTempLabel(NULL);
7106             if ( IC_TRUE(ifx) ) {
7107                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7108                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7109             } else {
7110                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7111                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7112             }
7113             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7114
7115                 {
7116                 /* left and right are both bit variables, result is carry */
7117                         resolvedIfx rIfx;
7118
7119                         resolveIfx(&rIfx,ifx);
7120
7121                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7122                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7123                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7124                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7125                         genSkipz2(&rIfx,0);
7126                 }
7127         } else {
7128
7129                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7130
7131                         /* They're not both bit variables. Is the right a literal? */
7132                         if(AOP_TYPE(right) == AOP_LIT) {
7133                         lit = ulFromVal (AOP(right)->aopu.aop_lit);
7134
7135                         switch(size) {
7136
7137                                 case 1:
7138                                         switch(lit & 0xff) {
7139                                                 case 1:
7140                                                                 if ( IC_TRUE(ifx) ) {
7141                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7142                                                                         emitSKPNZ;
7143                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7144                                                                 } else {
7145                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7146                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7147                                                                 }
7148                                                                 break;
7149                                                 case 0xff:
7150                                                                 if ( IC_TRUE(ifx) ) {
7151                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7152                                                                         emitSKPNZ;
7153                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7154                                                                 } else {
7155                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7156                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7157                                                                 }
7158                                                                 break;
7159                                                 default:
7160                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7161                                                                 if(lit)
7162                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7163                                                                 genSkip(ifx,'z');
7164                                         } // switch lit
7165
7166
7167                                         /* end of size == 1 */
7168                                         break;
7169
7170                                 case 2:
7171                                         genc16bit2lit(left,lit,offset);
7172                                         genSkip(ifx,'z');
7173                                         break;
7174                                         /* end of size == 2 */
7175
7176                                 default:
7177                                         /* size is 4 */
7178                                         if(lit==0) {
7179                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7180                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7181                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7182                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7183                                                 genSkip(ifx,'z');
7184                                         } else {
7185                                                 /* search for patterns that can be optimized */
7186
7187                                                 genc16bit2lit(left,lit,0);
7188                                                 lit >>= 16;
7189                                                 if(lit) {
7190                                                                 if(IC_TRUE(ifx))
7191                                                                 emitSKPZ; // if hi word unequal
7192                                                                 else
7193                                                                 emitSKPNZ; // if hi word equal
7194                                                                 // fail early
7195                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7196                                                         genc16bit2lit(left,lit,2);
7197                                                         genSkip(ifx,'z');
7198                                                 } else {
7199                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7200                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7201                                                         genSkip(ifx,'z');
7202                                                 }
7203                                         }
7204                                                 pic16_emitpLabel(falselbl->key);
7205                                                 break;
7206
7207                         } // switch size
7208
7209                         ifx->generated = 1;
7210                         goto release ;
7211
7212
7213           } else if(AOP_TYPE(right) == AOP_CRY ) {
7214             /* we know the left is not a bit, but that the right is */
7215             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7216             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7217                       pic16_popGet(AOP(right),offset));
7218             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7219
7220             /* if the two are equal, then W will be 0 and the Z bit is set
7221              * we could test Z now, or go ahead and check the high order bytes if
7222              * the variable we're comparing is larger than a byte. */
7223
7224             while(--size)
7225               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7226
7227             if ( IC_TRUE(ifx) ) {
7228               emitSKPNZ;
7229               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7230               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7231             } else {
7232               emitSKPZ;
7233               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7234               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7235             }
7236
7237           } else {
7238             /* They're both variables that are larger than bits */
7239             int s = size;
7240
7241             tlbl = newiTempLabel(NULL);
7242
7243             while(size--) {
7244               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7245               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7246
7247               if ( IC_TRUE(ifx) ) {
7248                 if(size) {
7249                   emitSKPZ;
7250
7251                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7252
7253                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7254                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7255                 } else {
7256                   emitSKPNZ;
7257
7258                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7259
7260
7261                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7262                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7263                 }
7264               } else {
7265                 emitSKPZ;
7266
7267                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7268
7269                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7270                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7271               }
7272               offset++;
7273             }
7274             if(s>1 && IC_TRUE(ifx)) {
7275               pic16_emitpLabel(tlbl->key);
7276               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7277             }
7278           }
7279         }
7280         /* mark the icode as generated */
7281         ifx->generated = 1;
7282         goto release ;
7283     }
7284
7285     /* if they are both bit variables */
7286     if (AOP_TYPE(left) == AOP_CRY &&
7287         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7288         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7289         if(AOP_TYPE(right) == AOP_LIT){
7290             unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
7291             if(lit == 0L){
7292                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7293                 pic16_emitcode("cpl","c");
7294             } else if(lit == 1L) {
7295                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296             } else {
7297                 pic16_emitcode("clr","c");
7298             }
7299             /* AOP_TYPE(right) == AOP_CRY */
7300         } else {
7301             symbol *lbl = newiTempLabel(NULL);
7302             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7303             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7304             pic16_emitcode("cpl","c");
7305             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7306         }
7307         /* c = 1 if egal */
7308         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7309             pic16_outBitC(result);
7310             goto release ;
7311         }
7312         if (ifx) {
7313             genIfxJump (ifx,"c");
7314             goto release ;
7315         }
7316         /* if the result is used in an arithmetic operation
7317         then put the result in place */
7318         pic16_outBitC(result);
7319     } else {
7320
7321       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7322       gencjne(left,right,result,ifx);
7323 /*
7324       if(ifx)
7325         gencjne(left,right,newiTempLabel(NULL));
7326       else {
7327         if(IC_TRUE(ifx)->key)
7328           gencjne(left,right,IC_TRUE(ifx)->key);
7329         else
7330           gencjne(left,right,IC_FALSE(ifx)->key);
7331         ifx->generated = 1;
7332         goto release ;
7333       }
7334       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7335         pic16_aopPut(AOP(result),"a",0);
7336         goto release ;
7337       }
7338
7339       if (ifx) {
7340         genIfxJump (ifx,"a");
7341         goto release ;
7342       }
7343 */
7344       /* if the result is used in an arithmetic operation
7345          then put the result in place */
7346 /*
7347       if (AOP_TYPE(result) != AOP_CRY)
7348         pic16_outAcc(result);
7349 */
7350       /* leave the result in acc */
7351     }
7352
7353 release:
7354     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7356     pic16_freeAsmop(result,NULL,ic,TRUE);
7357 }
7358 #endif
7359
7360 /*-----------------------------------------------------------------*/
7361 /* ifxForOp - returns the icode containing the ifx for operand     */
7362 /*-----------------------------------------------------------------*/
7363 static iCode *ifxForOp ( operand *op, iCode *ic )
7364 {
7365   FENTRY2;
7366
7367     /* if true symbol then needs to be assigned */
7368     if (IS_TRUE_SYMOP(op))
7369         return NULL ;
7370
7371     /* if this has register type condition and
7372     the next instruction is ifx with the same operand
7373     and live to of the operand is upto the ifx only then */
7374     if (ic->next
7375         && ic->next->op == IFX
7376         && IC_COND(ic->next)->key == op->key
7377         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7378         ) {
7379                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7380           return ic->next;
7381     }
7382
7383     /*
7384     if (ic->next &&
7385         ic->next->op == IFX &&
7386         IC_COND(ic->next)->key == op->key) {
7387       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7388       return ic->next;
7389     }
7390     */
7391
7392     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7393     if (ic->next &&
7394         ic->next->op == IFX)
7395       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7396
7397     if (ic->next &&
7398         ic->next->op == IFX &&
7399         IC_COND(ic->next)->key == op->key) {
7400       DEBUGpic16_emitcode ("; "," key is okay");
7401       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7402                            OP_SYMBOL(op)->liveTo,
7403                            ic->next->seq);
7404     }
7405
7406 #if 0
7407     /* the code below is completely untested
7408      * it just allows ulong2fs.c compile -- VR */
7409
7410     ic = ic->next;
7411     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7412                                         __FILE__, __FUNCTION__, __LINE__);
7413
7414     /* if this has register type condition and
7415     the next instruction is ifx with the same operand
7416     and live to of the operand is upto the ifx only then */
7417     if (ic->next &&
7418         ic->next->op == IFX &&
7419         IC_COND(ic->next)->key == op->key &&
7420         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7421         return ic->next;
7422
7423     if (ic->next &&
7424         ic->next->op == IFX &&
7425         IC_COND(ic->next)->key == op->key) {
7426       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7427       return ic->next;
7428     }
7429
7430     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7431                                         __FILE__, __FUNCTION__, __LINE__);
7432
7433 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7434 #endif
7435
7436     return NULL;
7437 }
7438 /*-----------------------------------------------------------------*/
7439 /* genAndOp - for && operation                                     */
7440 /*-----------------------------------------------------------------*/
7441 static void genAndOp (iCode *ic)
7442 {
7443   operand *left,*right, *result;
7444 /*     symbol *tlbl; */
7445
7446     FENTRY;
7447
7448     /* note here that && operations that are in an
7449     if statement are taken away by backPatchLabels
7450     only those used in arthmetic operations remain */
7451     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7452     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7453     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7454
7455     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7456
7457     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7458     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7459     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7460
7461     /* if both are bit variables */
7462 /*     if (AOP_TYPE(left) == AOP_CRY && */
7463 /*         AOP_TYPE(right) == AOP_CRY ) { */
7464 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7465 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7466 /*         pic16_outBitC(result); */
7467 /*     } else { */
7468 /*         tlbl = newiTempLabel(NULL); */
7469 /*         pic16_toBoolean(left);     */
7470 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7471 /*         pic16_toBoolean(right); */
7472 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7473 /*         pic16_outBitAcc(result); */
7474 /*     } */
7475
7476     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7478     pic16_freeAsmop(result,NULL,ic,TRUE);
7479 }
7480
7481
7482 /*-----------------------------------------------------------------*/
7483 /* genOrOp - for || operation                                      */
7484 /*-----------------------------------------------------------------*/
7485 /*
7486   tsd pic port -
7487   modified this code, but it doesn't appear to ever get called
7488 */
7489
7490 static void genOrOp (iCode *ic)
7491 {
7492   operand *left,*right, *result;
7493   symbol *tlbl;
7494
7495     FENTRY;
7496
7497   /* note here that || operations that are in an
7498     if statement are taken away by backPatchLabels
7499     only those used in arthmetic operations remain */
7500     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7501     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7502     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7503
7504     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7505
7506     /* if both are bit variables */
7507     if (AOP_TYPE(left) == AOP_CRY &&
7508         AOP_TYPE(right) == AOP_CRY ) {
7509       pic16_emitcode("clrc","");
7510       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7511                AOP(left)->aopu.aop_dir,
7512                AOP(left)->aopu.aop_dir);
7513       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7514                AOP(right)->aopu.aop_dir,
7515                AOP(right)->aopu.aop_dir);
7516       pic16_emitcode("setc","");
7517
7518     } else {
7519         tlbl = newiTempLabel(NULL);
7520         pic16_toBoolean(left);
7521         emitSKPZ;
7522         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7523         pic16_toBoolean(right);
7524         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7525
7526         pic16_outBitAcc(result);
7527     }
7528
7529     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7531     pic16_freeAsmop(result,NULL,ic,TRUE);
7532 }
7533
7534 /*-----------------------------------------------------------------*/
7535 /* isLiteralBit - test if lit == 2^n                               */
7536 /*-----------------------------------------------------------------*/
7537 static int isLiteralBit(unsigned long lit)
7538 {
7539     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7540     0x100L,0x200L,0x400L,0x800L,
7541     0x1000L,0x2000L,0x4000L,0x8000L,
7542     0x10000L,0x20000L,0x40000L,0x80000L,
7543     0x100000L,0x200000L,0x400000L,0x800000L,
7544     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7545     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7546     int idx;
7547
7548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7549     for(idx = 0; idx < 32; idx++)
7550         if(lit == pw[idx])
7551             return idx+1;
7552     return 0;
7553 }
7554
7555 /*-----------------------------------------------------------------*/
7556 /* continueIfTrue -                                                */
7557 /*-----------------------------------------------------------------*/
7558 static void continueIfTrue (iCode *ic)
7559 {
7560   FENTRY;
7561   if(IC_TRUE(ic))
7562     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7563   ic->generated = 1;
7564 }
7565
7566 /*-----------------------------------------------------------------*/
7567 /* jmpIfTrue -                                                     */
7568 /*-----------------------------------------------------------------*/
7569 static void jumpIfTrue (iCode *ic)
7570 {
7571   FENTRY;
7572   if(!IC_TRUE(ic))
7573     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7574   ic->generated = 1;
7575 }
7576
7577 /*-----------------------------------------------------------------*/
7578 /* jmpTrueOrFalse -                                                */
7579 /*-----------------------------------------------------------------*/
7580 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7581 {
7582   // ugly but optimized by peephole
7583   FENTRY;
7584   if(IC_TRUE(ic)){
7585     symbol *nlbl = newiTempLabel(NULL);
7586       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
7587       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7588       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7589       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7590   } else {
7591     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7592     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7593   }
7594   ic->generated = 1;
7595 }
7596
7597 /*-----------------------------------------------------------------*/
7598 /* genAnd  - code for and                                          */
7599 /*-----------------------------------------------------------------*/
7600 static void genAnd (iCode *ic, iCode *ifx)
7601 {
7602   operand *left, *right, *result;
7603   int size, offset = 0;
7604   unsigned long lit = 0L;
7605   resolvedIfx rIfx;
7606
7607   FENTRY;
7608
7609   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7610   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7611   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7612
7613   resolveIfx (&rIfx, ifx);
7614
7615   /* if left is a literal & right is not then exchange them */
7616   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7617       AOP_NEEDSACC (left))
7618     {
7619       operand *tmp = right;
7620       right = left;
7621       left = tmp;
7622     }
7623
7624   /* if result = right then exchange them */
7625   if (pic16_sameRegs (AOP (result), AOP (right)))
7626     {
7627       operand *tmp = right;
7628       right = left;
7629       left = tmp;
7630     }
7631
7632   /* if right is bit then exchange them */
7633   if (AOP_TYPE (right) == AOP_CRY &&
7634       AOP_TYPE (left) != AOP_CRY)
7635     {
7636       operand *tmp = right;
7637       right = left;
7638       left = tmp;
7639     }
7640
7641   if (AOP_TYPE (right) == AOP_LIT)
7642     lit = ulFromVal (AOP (right)->aopu.aop_lit);
7643
7644   size = AOP_SIZE (result);
7645
7646   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
7647
7648   // if(bit & yy)
7649   // result = bit & yy;
7650   if (AOP_TYPE(left) == AOP_CRY){
7651     // c = bit & literal;
7652     if(AOP_TYPE(right) == AOP_LIT){
7653       if(lit & 1) {
7654         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7655           // no change
7656           goto release;
7657         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7658       } else {
7659         // bit(result) = 0;
7660         if(size && (AOP_TYPE(result) == AOP_CRY)){
7661           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7662           goto release;
7663         }
7664         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7665           jumpIfTrue(ifx);
7666           goto release;
7667         }
7668         pic16_emitcode("clr","c");
7669       }
7670     } else {
7671       if (AOP_TYPE(right) == AOP_CRY){
7672         // c = bit & bit;
7673         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7674         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7675       } else {
7676         // c = bit & val;
7677         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7678         // c = lsb
7679         pic16_emitcode("rrc","a");
7680         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7681       }
7682     }
7683     // bit = c
7684     // val = c
7685     if(size)
7686       pic16_outBitC(result);
7687     // if(bit & ...)
7688     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7689       genIfxJump(ifx, "c");
7690     goto release ;
7691   }
7692
7693   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
7694   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7695   if ((AOP_TYPE (right) == AOP_LIT) &&
7696      (AOP_TYPE (result) == AOP_CRY) &&
7697      (AOP_TYPE (left) != AOP_CRY))
7698     {
7699       symbol *tlbl = newiTempLabel (NULL);
7700       int sizel = AOP_SIZE (left);
7701       int nonnull = 0;
7702       char emitBra;
7703
7704       if (size)
7705         emitSETC;
7706
7707       /* get number of non null bytes in literal */
7708       while (sizel--)
7709         {
7710           if (lit & (0xff << (sizel * 8)))
7711             ++nonnull;
7712         }
7713
7714       emitBra = nonnull || rIfx.condition;
7715
7716       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
7717         {
7718           unsigned char bytelit = lit;
7719
7720           if (bytelit != 0)
7721             {
7722               int posbit;
7723
7724               --nonnull;
7725
7726               /* patch provided by Aaron Colwell */
7727               if ((posbit = isLiteralBit (bytelit)) != 0)
7728                 {
7729                   if (nonnull)
7730                     {
7731                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
7732                       pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
7733                     }
7734                   else
7735                     {
7736                       pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
7737                     }
7738                 }
7739               else
7740                 {
7741                   if (bytelit == 0xff)
7742                     {
7743                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
7744                        * a peephole could optimize it out -- VR */
7745                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
7746                     }
7747                   else
7748                     {
7749                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
7750                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
7751                     }
7752                   if (nonnull)
7753                     {
7754                       if (rIfx.condition)
7755                         {
7756                           emitSKPZ;
7757                           pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
7758                         }
7759                       else
7760                         {
7761                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
7762                         }
7763                     }
7764                   else
7765                     {
7766                       /* last non null byte */
7767                       if (rIfx.condition)
7768                         emitSKPZ;
7769                       else
7770                         emitSKPNZ;
7771                     }
7772                 }
7773             }
7774         }
7775
7776       // bit = left & literal
7777       if (size)
7778         {
7779           emitCLRC;
7780           pic16_emitpLabel (tlbl->key);
7781         }
7782
7783       // if(left & literal)
7784       else
7785         {
7786           if (ifx)
7787             {
7788               if (emitBra)
7789                 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
7790               ifx->generated = 1;
7791             }
7792           pic16_emitpLabel (tlbl->key);
7793           goto release;
7794         }
7795       pic16_outBitC (result);
7796       goto release;
7797     }
7798
7799   /* if left is same as result */
7800   if(pic16_sameRegs(AOP(result),AOP(left))){
7801     int know_W = -1;
7802     for(;size--; offset++,lit>>=8) {
7803       if(AOP_TYPE(right) == AOP_LIT){
7804         switch(lit & 0xff) {
7805         case 0x00:
7806           /*  and'ing with 0 has clears the result */
7807 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7808           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7809           break;
7810         case 0xff:
7811           /* and'ing with 0xff is a nop when the result and left are the same */
7812           break;
7813
7814         default:
7815           {
7816             int p = pic16_my_powof2( (~lit) & 0xff );
7817             if(p>=0) {
7818               /* only one bit is set in the literal, so use a bcf instruction */
7819 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7820               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7821
7822             } else {
7823               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7824               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7825               if(know_W != (lit&0xff))
7826                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7827               know_W = lit &0xff;
7828               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7829             }
7830           }
7831         }
7832       } else {
7833         if (AOP_TYPE(left) == AOP_ACC) {
7834           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7835         } else {
7836           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7837           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7838
7839         }
7840       }
7841     }
7842
7843   } else {
7844     // left & result in different registers
7845     if(AOP_TYPE(result) == AOP_CRY){
7846       // result = bit
7847       // if(size), result in bit
7848       // if(!size && ifx), conditional oper: if(left & right)
7849       symbol *tlbl = newiTempLabel(NULL);
7850       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7851       if(size)
7852         pic16_emitcode("setb","c");
7853       while(sizer--){
7854         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7855         pic16_emitcode("anl","a,%s",
7856                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7857         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7858         offset++;
7859       }
7860       if(size){
7861         CLRC;
7862         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7863         pic16_outBitC(result);
7864       } else if(ifx)
7865         jmpTrueOrFalse(ifx, tlbl);
7866     } else {
7867       for(;(size--);offset++) {
7868         // normal case
7869         // result = left & right
7870         if(AOP_TYPE(right) == AOP_LIT){
7871           int t = (lit >> (offset*8)) & 0x0FFL;
7872           switch(t) {
7873           case 0x00:
7874             pic16_emitcode("clrf","%s",
7875                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7876             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7877             break;
7878           case 0xff:
7879             pic16_emitcode("movf","%s,w",
7880                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7881             pic16_emitcode("movwf","%s",
7882                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7883             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7884             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7885             break;
7886           default:
7887             pic16_emitcode("movlw","0x%x",t);
7888             pic16_emitcode("andwf","%s,w",
7889                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890             pic16_emitcode("movwf","%s",
7891                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7892
7893             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7894             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7895             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7896           }
7897           continue;
7898         }
7899
7900         if (AOP_TYPE(left) == AOP_ACC) {
7901           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7903         } else {
7904           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7905           pic16_emitcode("andwf","%s,w",
7906                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7908           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7909         }
7910         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7911         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7912       }
7913     }
7914   }
7915
7916 release :
7917   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7918   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7919   pic16_freeAsmop(result,NULL,ic,TRUE);
7920 }
7921
7922 /*-----------------------------------------------------------------*/
7923 /* genOr  - code for or                                            */
7924 /*-----------------------------------------------------------------*/
7925 static void genOr (iCode *ic, iCode *ifx)
7926 {
7927   operand *left, *right, *result;
7928   int size, offset = 0;
7929   unsigned long lit = 0L;
7930   resolvedIfx rIfx;
7931
7932   FENTRY;
7933
7934   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7935   pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
7936   pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
7937
7938   resolveIfx (&rIfx, ifx);
7939
7940   /* if left is a literal & right is not then exchange them */
7941   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7942       AOP_NEEDSACC (left))
7943     {
7944       operand *tmp = right;
7945       right = left;
7946       left = tmp;
7947     }
7948
7949   /* if result = right then exchange them */
7950   if (pic16_sameRegs (AOP (result), AOP (right)))
7951     {
7952       operand *tmp = right;
7953       right = left;
7954       left = tmp;
7955     }
7956
7957   /* if right is bit then exchange them */
7958   if (AOP_TYPE (right) == AOP_CRY &&
7959       AOP_TYPE (left) != AOP_CRY)
7960     {
7961       operand *tmp = right;
7962       right = left;
7963       left = tmp;
7964     }
7965
7966   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
7967
7968   if (AOP_TYPE (right) == AOP_LIT)
7969       lit = ulFromVal (AOP (right)->aopu.aop_lit);
7970
7971   size = AOP_SIZE (result);
7972
7973   // if(bit | yy)
7974   // xx = bit | yy;
7975   if (AOP_TYPE(left) == AOP_CRY){
7976       if(AOP_TYPE(right) == AOP_LIT){
7977           // c = bit & literal;
7978           if(lit){
7979               // lit != 0 => result = 1
7980               if(AOP_TYPE(result) == AOP_CRY){
7981                 if(size)
7982                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7983                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7984                 //     AOP(result)->aopu.aop_dir,
7985                 //     AOP(result)->aopu.aop_dir);
7986                   else if(ifx)
7987                       continueIfTrue(ifx);
7988                   goto release;
7989               }
7990           } else {
7991               // lit == 0 => result = left
7992               if(size && pic16_sameRegs(AOP(result),AOP(left)))
7993                   goto release;
7994               pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7995           }
7996       } else {
7997           if (AOP_TYPE(right) == AOP_CRY){
7998             if(pic16_sameRegs(AOP(result),AOP(left))){
7999               // c = bit | bit;
8000               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8001               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8002               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8003
8004               pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8005                        AOP(result)->aopu.aop_dir,
8006                        AOP(result)->aopu.aop_dir);
8007               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8008                        AOP(right)->aopu.aop_dir,
8009                        AOP(right)->aopu.aop_dir);
8010               pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8011                        AOP(result)->aopu.aop_dir,
8012                        AOP(result)->aopu.aop_dir);
8013             } else {
8014               if( AOP_TYPE(result) == AOP_ACC) {
8015                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8016                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8017                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8018                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8019
8020               } else {
8021
8022                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8023                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8024                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8025                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8026
8027                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8028                                AOP(result)->aopu.aop_dir,
8029                                AOP(result)->aopu.aop_dir);
8030                 pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8031                                AOP(right)->aopu.aop_dir,
8032                                AOP(right)->aopu.aop_dir);
8033                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8034                                AOP(left)->aopu.aop_dir,
8035                                AOP(left)->aopu.aop_dir);
8036                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8037                                AOP(result)->aopu.aop_dir,
8038                                AOP(result)->aopu.aop_dir);
8039               }
8040             }
8041           } else {
8042               // c = bit | val;
8043               symbol *tlbl = newiTempLabel(NULL);
8044               pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8045
8046
8047               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8048               if( AOP_TYPE(right) == AOP_ACC) {
8049                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8050                 emitSKPNZ;
8051                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8052                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8053               }
8054
8055
8056
8057               if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8058                   pic16_emitcode(";XXX setb","c");
8059               pic16_emitcode(";XXX jb","%s,%05d_DS_",
8060                        AOP(left)->aopu.aop_dir,tlbl->key+100);
8061               pic16_toBoolean(right);
8062               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8063               if((AOP_TYPE(result) == AOP_CRY) && ifx){
8064                   jmpTrueOrFalse(ifx, tlbl);
8065                   goto release;
8066               } else {
8067                   CLRC;
8068                   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8069               }
8070           }
8071       }
8072       // bit = c
8073       // val = c
8074       if(size)
8075           pic16_outBitC(result);
8076       // if(bit | ...)
8077       else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8078           genIfxJump(ifx, "c");
8079       goto release ;
8080   }
8081
8082   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8083   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8084   if ((AOP_TYPE (right) == AOP_LIT) &&
8085      (AOP_TYPE (result) == AOP_CRY) &&
8086      (AOP_TYPE (left) != AOP_CRY))
8087     {
8088       if (lit)
8089         {
8090           if (rIfx.condition)
8091             pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
8092           ifx->generated = 1;
8093         }
8094       else
8095         wassert (0);
8096
8097       goto release;
8098   }
8099
8100   /* if left is same as result */
8101   if(pic16_sameRegs(AOP(result),AOP(left))){
8102     int know_W = -1;
8103     for(;size--; offset++,lit>>=8) {
8104       if(AOP_TYPE(right) == AOP_LIT){
8105         if((lit & 0xff) == 0)
8106           /*  or'ing with 0 has no effect */
8107           continue;
8108         else {
8109           int p = pic16_my_powof2(lit & 0xff);
8110           if(p>=0) {
8111             /* only one bit is set in the literal, so use a bsf instruction */
8112             pic16_emitpcode(POC_BSF,
8113                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8114           } else {
8115             if(know_W != (lit & 0xff))
8116               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8117             know_W = lit & 0xff;
8118             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8119           }
8120
8121         }
8122       } else {
8123         if (AOP_TYPE(left) == AOP_ACC) {
8124           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8125 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126         } else {
8127           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8128           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8129
8130 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8131 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8132
8133         }
8134       }
8135     }
8136   } else {
8137       // left & result in different registers
8138       if(AOP_TYPE(result) == AOP_CRY){
8139           // result = bit
8140           // if(size), result in bit
8141           // if(!size && ifx), conditional oper: if(left | right)
8142           symbol *tlbl = newiTempLabel(NULL);
8143           int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8144           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8145
8146
8147           if(size)
8148               pic16_emitcode(";XXX setb","c");
8149           while(sizer--){
8150               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151               pic16_emitcode(";XXX orl","a,%s",
8152                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8154               offset++;
8155           }
8156           if(size){
8157               CLRC;
8158               pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8159               pic16_outBitC(result);
8160           } else if(ifx)
8161               jmpTrueOrFalse(ifx, tlbl);
8162       } else for(;(size--);offset++){
8163         // normal case
8164         // result = left & right
8165         if(AOP_TYPE(right) == AOP_LIT){
8166           int t = (lit >> (offset*8)) & 0x0FFL;
8167           switch(t) {
8168           case 0x00:
8169             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8170             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8171
8172 //            pic16_emitcode("movf","%s,w",
8173 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174 //            pic16_emitcode("movwf","%s",
8175 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8176             break;
8177           default:
8178             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8179             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8180             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8181
8182 //            pic16_emitcode("movlw","0x%x",t);
8183 //            pic16_emitcode("iorwf","%s,w",
8184 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8185 //            pic16_emitcode("movwf","%s",
8186 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8187
8188           }
8189           continue;
8190         }
8191
8192         // faster than result <- left, anl result,right
8193         // and better if result is SFR
8194         if (AOP_TYPE(left) == AOP_ACC) {
8195           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8196 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8197         } else {
8198           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8199           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8200
8201 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8202 //          pic16_emitcode("iorwf","%s,w",
8203 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8204         }
8205         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8206 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8207       }
8208   }
8209
8210 release :
8211   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8212   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8213   pic16_freeAsmop(result,NULL,ic,TRUE);
8214 }
8215
8216 /*-----------------------------------------------------------------*/
8217 /* genXor - code for xclusive or                                   */
8218 /*-----------------------------------------------------------------*/
8219 static void genXor (iCode *ic, iCode *ifx)
8220 {
8221   operand *left, *right, *result;
8222   int size, offset = 0;
8223   unsigned long lit = 0L;
8224   resolvedIfx rIfx;
8225
8226   FENTRY;
8227
8228   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
8229   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
8230   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
8231
8232   resolveIfx (&rIfx,ifx);
8233
8234   /* if left is a literal & right is not ||
8235      if left needs acc & right does not */
8236   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
8237       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
8238     {
8239       operand *tmp = right;
8240       right = left;
8241       left = tmp;
8242     }
8243
8244   /* if result = right then exchange them */
8245   if (pic16_sameRegs (AOP (result), AOP (right)))
8246     {
8247       operand *tmp = right ;
8248       right = left;
8249       left = tmp;
8250     }
8251
8252   /* if right is bit then exchange them */
8253   if (AOP_TYPE (right) == AOP_CRY &&
8254       AOP_TYPE (left) != AOP_CRY)
8255     {
8256       operand *tmp = right ;
8257       right = left;
8258       left = tmp;
8259     }
8260
8261   if (AOP_TYPE (right) == AOP_LIT)
8262     lit = ulFromVal (AOP (right)->aopu.aop_lit);
8263
8264   size = AOP_SIZE (result);
8265
8266   // if(bit ^ yy)
8267   // xx = bit ^ yy;
8268   if (AOP_TYPE(left) == AOP_CRY)
8269     {
8270       if (AOP_TYPE(right) == AOP_LIT)
8271         {
8272           // c = bit & literal;
8273           if (lit >> 1)
8274             {
8275               // lit>>1  != 0 => result = 1
8276               if (AOP_TYPE(result) == AOP_CRY)
8277                 {
8278                   if (size)
8279                     {
8280                       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
8281                       pic16_emitcode("setb", "%s", AOP(result)->aopu.aop_dir);
8282                     }
8283                   else if (ifx)
8284                     continueIfTrue(ifx);
8285                   goto release;
8286                 }
8287               pic16_emitcode("setb", "c");
8288             }
8289           else
8290             {
8291               // lit == (0 or 1)
8292               if (lit == 0)
8293                 {
8294                   // lit == 0, result = left
8295                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
8296                     goto release;
8297                   pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
8298                 }
8299               else
8300                 {
8301                   // lit == 1, result = not(left)
8302                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
8303                     {
8304                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
8305                       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
8306                       pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
8307                       goto release;
8308                     }
8309                   else
8310                     {
8311                       pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
8312                       pic16_emitcode("cpl", "c");
8313                     }
8314                 }
8315             }
8316         }
8317       else
8318         {
8319           // right != literal
8320           symbol *tlbl = newiTempLabel(NULL);
8321           if (AOP_TYPE(right) == AOP_CRY)
8322             {
8323               // c = bit ^ bit;
8324               pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
8325             }
8326           else
8327             {
8328               int sizer = AOP_SIZE(right);
8329               // c = bit ^ val
8330               // if val>>1 != 0, result = 1
8331               pic16_emitcode("setb", "c");
8332               while (sizer)
8333                 {
8334                   MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
8335                   if (sizer == 1)
8336                     // test the msb of the lsb
8337                     pic16_emitcode("anl", "a,#0xfe");
8338                   pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
8339                   sizer--;
8340                 }
8341               // val = (0,1)
8342               pic16_emitcode("rrc", "a");
8343             }
8344           pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
8345           pic16_emitcode("cpl", "c");
8346           pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
8347         }
8348       // bit = c
8349       // val = c
8350       if (size)
8351         pic16_outBitC(result);
8352       // if(bit | ...)
8353       else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
8354         genIfxJump(ifx, "c");
8355       goto release;
8356     }
8357
8358   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
8359   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
8360   if ((AOP_TYPE (right) == AOP_LIT) &&
8361      (AOP_TYPE (result) == AOP_CRY) &&
8362      (AOP_TYPE (left) != AOP_CRY))
8363     {
8364       symbol *tlbl = newiTempLabel (NULL);
8365       int sizel;
8366
8367       if (size)
8368         emitSETC;
8369
8370       for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
8371         {
8372           unsigned char bytelit = lit;
8373
8374           switch (bytelit)
8375             {
8376             case 0xff:
8377               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
8378               break;
8379
8380             case 0x00:
8381               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
8382               break;
8383
8384             default:
8385               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
8386               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
8387               break;
8388             }
8389           if (sizel)
8390             {
8391               if (rIfx.condition)
8392                 {
8393                   emitSKPZ;
8394                   pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
8395                 }
8396               else
8397                 {
8398                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
8399                 }
8400             }
8401           else
8402             {
8403               /* last non null byte */
8404               if (rIfx.condition)
8405                 emitSKPZ;
8406               else
8407                 emitSKPNZ;
8408             }
8409         }
8410
8411       // bit = left ^ literal
8412       if (size)
8413         {
8414           emitCLRC;
8415           pic16_emitpLabel (tlbl->key);
8416         }
8417       // if (left ^ literal)
8418       else
8419         {
8420           if (ifx)
8421             {
8422               pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
8423               ifx->generated = 1;
8424             }
8425           pic16_emitpLabel (tlbl->key);
8426           goto release;
8427         }
8428
8429       pic16_outBitC (result);
8430       goto release;
8431   }
8432
8433   if (pic16_sameRegs(AOP(result), AOP(left)))
8434     {
8435       /* if left is same as result */
8436       for (; size--; offset++)
8437         {
8438           if (AOP_TYPE(right) == AOP_LIT)
8439             {
8440               int t  = (lit >> (offset * 8)) & 0x0FFL;
8441               if  (t == 0x00L)
8442                 continue;
8443               else
8444                 if (IS_AOP_PREG(left))
8445                   {
8446                     MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8447                     pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(left), offset, FALSE, TRUE));
8448                     pic16_aopPut(AOP(result), "a", offset);
8449                   }
8450                 else
8451                   {
8452                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8453                     pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
8454                     pic16_emitcode("xrl", "%s,%s",
8455                                    pic16_aopGet(AOP(left), offset, FALSE, TRUE),
8456                                    pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8457                   }
8458             }
8459           else
8460             {
8461               if (AOP_TYPE(left) == AOP_ACC)
8462                 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8463               else
8464                 {
8465                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
8466                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
8467                 }
8468             }
8469         }
8470     }
8471   else
8472     {
8473     // left ^ result in different registers
8474     if (AOP_TYPE(result) == AOP_CRY)
8475       {
8476         // result = bit
8477         // if(size), result in bit
8478         // if(!size && ifx), conditional oper: if(left ^ right)
8479         symbol *tlbl = newiTempLabel(NULL);
8480         int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
8481         if (size)
8482           pic16_emitcode("setb", "c");
8483         while (sizer--)
8484           {
8485             if ((AOP_TYPE(right) == AOP_LIT) &&
8486               (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
8487               {
8488                 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8489               }
8490             else
8491               {
8492                 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8493                 pic16_emitcode("xrl", "a,%s",
8494                                pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8495               }
8496             pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
8497             offset++;
8498           }
8499         if (size)
8500           {
8501             CLRC;
8502             pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
8503             pic16_outBitC(result);
8504           }
8505         else if (ifx)
8506           jmpTrueOrFalse(ifx, tlbl);
8507       }
8508     else
8509       {
8510         for (; (size--); offset++)
8511           {
8512             // normal case
8513             // result = left ^ right
8514             if (AOP_TYPE(right) == AOP_LIT)
8515               {
8516                 int t = (lit >> (offset * 8)) & 0x0FFL;
8517                 switch(t)
8518                   {
8519                   case 0x00:
8520                     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
8521                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8522                     pic16_emitcode("movf", "%s,w",
8523                                    pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8524                     pic16_emitcode("movwf", "%s",
8525                                    pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8526                     break;
8527
8528                   case 0xff:
8529                     pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
8530                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8531                     pic16_emitcode("comf", "%s,w",
8532                                    pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8533                     pic16_emitcode("movwf", "%s",
8534                                    pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8535                     break;
8536
8537                   default:
8538                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8539                     pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
8540                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8541                     pic16_emitcode("movlw", "0x%x", t);
8542                     pic16_emitcode("xorwf", "%s,w",
8543                                    pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8544                     pic16_emitcode("movwf", "%s",
8545                                    pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8546
8547                   }
8548                 continue;
8549               }
8550
8551             // faster than result <- left, anl result,right
8552             // and better if result is SFR
8553             if (AOP_TYPE(left) == AOP_ACC)
8554               {
8555                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
8556                 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8557               }
8558             else
8559               {
8560                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
8561                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
8562                 pic16_emitcode("movf", "%s,w", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
8563                 pic16_emitcode("xorwf", "%s,w", pic16_aopGet(AOP(left), offset, FALSE, FALSE));
8564               }
8565             if ( AOP_TYPE(result) != AOP_ACC)
8566               {
8567                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8568                 pic16_emitcode("movwf", "%s", pic16_aopGet(AOP(result), offset, FALSE, FALSE));
8569               }
8570           }
8571       }
8572   }
8573
8574 release :
8575   pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
8576   pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
8577   pic16_freeAsmop(result, NULL, ic, TRUE);
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* genInline - write the inline code out                           */
8582 /*-----------------------------------------------------------------*/
8583 static void genInline (iCode *ic)
8584 {
8585   char *buffer, *bp, *bp1;
8586   bool inComment = FALSE;
8587
8588   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8589
8590   _G.inLine += (!options.asmpeep);
8591
8592   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
8593
8594   while((bp1=strstr(bp, "\\n"))) {
8595     *bp1++ = '\n';
8596     *bp1++ = ' ';
8597     bp = bp1;
8598   }
8599   bp = bp1 = buffer;
8600
8601 #if 0
8602   /* This is an experimental code for #pragma inline
8603      and is temporarily disabled for 2.5.0 release */
8604   if(asmInlineMap)
8605   {
8606     symbol *sym;
8607     char *s;
8608     char *cbuf;
8609     int cblen;
8610
8611       cbuf = Safe_strdup(buffer);
8612       cblen = strlen(buffer)+1;
8613       memset(cbuf, 0, cblen);
8614
8615       bp = buffer;
8616       bp1 = cbuf;
8617       while(*bp) {
8618         if(*bp != '%')*bp1++ = *bp++;
8619         else {
8620           int i;
8621
8622             bp++;
8623             i = *bp - '0';
8624             if(i>elementsInSet(asmInlineMap))break;
8625
8626             bp++;
8627             s = indexSet(asmInlineMap, i);
8628             DEBUGpc("searching symbol s = `%s'", s);
8629             sym = findSym(SymbolTab, NULL, s);
8630
8631             if(sym->reqv) {
8632               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8633             } else {
8634               strcat(bp1, sym->rname);
8635             }
8636
8637             while(*bp1)bp1++;
8638         }
8639
8640         if(strlen(bp1) > cblen - 16) {
8641           int i = strlen(cbuf);
8642           cblen += 50;
8643           cbuf = realloc(cbuf, cblen);
8644           memset(cbuf+i, 0, 50);
8645           bp1 = cbuf + i;
8646         }
8647       }
8648
8649       free(buffer);
8650       buffer = Safe_strdup( cbuf );
8651       free(cbuf);
8652
8653       bp = bp1 = buffer;
8654   }
8655 #endif  /* 0 */
8656
8657   /* emit each line as a code */
8658   while (*bp)
8659     {
8660       switch (*bp)
8661         {
8662         case ';':
8663           inComment = TRUE;
8664           ++bp;
8665           break;
8666
8667         case '\n':
8668           inComment = FALSE;
8669           *bp++ = '\0';
8670           if (*bp1)
8671             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8672           bp1 = bp;
8673           break;
8674
8675         default:
8676           /* Add \n for labels, not dirs such as c:\mydir */
8677           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8678             {
8679               ++bp;
8680               *bp = '\0';
8681               ++bp;
8682               /* print label, use this special format with NULL directive
8683                * to denote that the argument should not be indented with tab */
8684               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8685               bp1 = bp;
8686             }
8687           else
8688             ++bp;
8689           break;
8690         }
8691     }
8692
8693   if ((bp1 != bp) && *bp1)
8694     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8695
8696   Safe_free (buffer);
8697
8698   _G.inLine -= (!options.asmpeep);
8699 }
8700
8701 /*-----------------------------------------------------------------*/
8702 /* genRRC - rotate right with carry                                */
8703 /*-----------------------------------------------------------------*/
8704 static void genRRC (iCode *ic)
8705 {
8706   operand *left , *result ;
8707   int size, offset = 0, same;
8708
8709   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8710
8711   /* rotate right with carry */
8712   left = IC_LEFT(ic);
8713   result=IC_RESULT(ic);
8714   pic16_aopOp (left,ic,FALSE);
8715   pic16_aopOp (result,ic,TRUE);
8716
8717   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8718
8719   same = pic16_sameRegs(AOP(result),AOP(left));
8720
8721   size = AOP_SIZE(result);
8722
8723   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8724
8725   /* get the lsb and put it into the carry */
8726   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8727
8728   offset = 0 ;
8729
8730   while(size--) {
8731
8732     if(same) {
8733       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8734     } else {
8735       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8736       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8737     }
8738
8739     offset++;
8740   }
8741
8742   pic16_freeAsmop(left,NULL,ic,TRUE);
8743   pic16_freeAsmop(result,NULL,ic,TRUE);
8744 }
8745
8746 /*-----------------------------------------------------------------*/
8747 /* genRLC - generate code for rotate left with carry               */
8748 /*-----------------------------------------------------------------*/
8749 static void genRLC (iCode *ic)
8750 {
8751   operand *left , *result ;
8752   int size, offset = 0;
8753   int same;
8754
8755   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8756   /* rotate right with carry */
8757   left = IC_LEFT(ic);
8758   result=IC_RESULT(ic);
8759   pic16_aopOp (left,ic,FALSE);
8760   pic16_aopOp (result,ic,TRUE);
8761
8762   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8763
8764   same = pic16_sameRegs(AOP(result),AOP(left));
8765
8766   /* move it to the result */
8767   size = AOP_SIZE(result);
8768
8769   /* get the msb and put it into the carry */
8770   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8771
8772   offset = 0 ;
8773
8774   while(size--) {
8775
8776     if(same) {
8777       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8778     } else {
8779       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8780       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8781     }
8782
8783     offset++;
8784   }
8785
8786
8787   pic16_freeAsmop(left,NULL,ic,TRUE);
8788   pic16_freeAsmop(result,NULL,ic,TRUE);
8789 }
8790
8791
8792 /* gpasm can get the highest order bit with HIGH/UPPER
8793  * so the following probably is not needed -- VR */
8794
8795 /*-----------------------------------------------------------------*/
8796 /* genGetHbit - generates code get highest order bit               */
8797 /*-----------------------------------------------------------------*/
8798 static void genGetHbit (iCode *ic)
8799 {
8800     operand *left, *result;
8801     left = IC_LEFT(ic);
8802     result=IC_RESULT(ic);
8803     pic16_aopOp (left,ic,FALSE);
8804     pic16_aopOp (result,ic,FALSE);
8805
8806     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8807     /* get the highest order byte into a */
8808     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8809     if(AOP_TYPE(result) == AOP_CRY){
8810         pic16_emitcode("rlc","a");
8811         pic16_outBitC(result);
8812     }
8813     else{
8814         pic16_emitcode("rl","a");
8815         pic16_emitcode("anl","a,#0x01");
8816         pic16_outAcc(result);
8817     }
8818
8819
8820     pic16_freeAsmop(left,NULL,ic,TRUE);
8821     pic16_freeAsmop(result,NULL,ic,TRUE);
8822 }
8823
8824 #if 0
8825 /*-----------------------------------------------------------------*/
8826 /* AccRol - rotate left accumulator by known count                 */
8827 /*-----------------------------------------------------------------*/
8828 static void AccRol (int shCount)
8829 {
8830     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8831     shCount &= 0x0007;              // shCount : 0..7
8832     switch(shCount){
8833         case 0 :
8834             break;
8835         case 1 :
8836             pic16_emitcode("rl","a");
8837             break;
8838         case 2 :
8839             pic16_emitcode("rl","a");
8840             pic16_emitcode("rl","a");
8841             break;
8842         case 3 :
8843             pic16_emitcode("swap","a");
8844             pic16_emitcode("rr","a");
8845             break;
8846         case 4 :
8847             pic16_emitcode("swap","a");
8848             break;
8849         case 5 :
8850             pic16_emitcode("swap","a");
8851             pic16_emitcode("rl","a");
8852             break;
8853         case 6 :
8854             pic16_emitcode("rr","a");
8855             pic16_emitcode("rr","a");
8856             break;
8857         case 7 :
8858             pic16_emitcode("rr","a");
8859             break;
8860     }
8861 }
8862 #endif
8863
8864 /*-----------------------------------------------------------------*/
8865 /* AccLsh - left shift accumulator by known count                  */
8866 /*-----------------------------------------------------------------*/
8867 static void AccLsh (int shCount, int doMask)
8868 {
8869         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8870         switch(shCount){
8871                 case 0 :
8872                         return;
8873                         break;
8874                 case 1 :
8875                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8876                         break;
8877                 case 2 :
8878                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8879                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8880                         break;
8881                 case 3 :
8882                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8883                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8884                         break;
8885                 case 4 :
8886                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8887                         break;
8888                 case 5 :
8889                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8890                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8891                         break;
8892                 case 6 :
8893                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8894                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8895                         break;
8896                 case 7 :
8897                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8898                         break;
8899         }
8900         if (doMask) {
8901                 /* no masking is required in genPackBits */
8902                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8903         }
8904 }
8905
8906 /*-----------------------------------------------------------------*/
8907 /* AccRsh - right shift accumulator by known count                 */
8908 /*-----------------------------------------------------------------*/
8909 static void AccRsh (int shCount, int andmask)
8910 {
8911         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8912         assert ((shCount >= 0) && (shCount <= 8));
8913         switch (shCount) {
8914                 case 0 :
8915                         return; break;
8916                 case 1 :
8917                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8918                         break;
8919                 case 2 :
8920                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8921                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8922                         break;
8923                 case 3 :
8924                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8925                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8926                         break;
8927                 case 4 :
8928                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8929                         break;
8930                 case 5 :
8931                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8932                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8933                         break;
8934                 case 6 :
8935                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8936                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8937                         break;
8938                 case 7 :
8939                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8940                         break;
8941                 default:
8942                         // Rotating by 8 is a NOP.
8943                         break;
8944         }
8945
8946         if (andmask)
8947                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8948         else
8949                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8950 }
8951
8952 /*-----------------------------------------------------------------*/
8953 /* shiftR1Left2Result - shift right one byte from left to result   */
8954 /*-----------------------------------------------------------------*/
8955 static void shiftR1Left2ResultSigned (operand *left, int offl,
8956                                 operand *result, int offr,
8957                                 int shCount)
8958 {
8959   int same;
8960
8961   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8962   assert ((shCount >= 0) && (shCount <= 8));
8963
8964   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8965
8966   /* Do NOT use result for intermediate results, it might be an SFR!. */
8967   switch (shCount) {
8968   case 0:
8969     if (!same) {
8970       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
8971       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
8972     }
8973     break;
8974
8975   case 1:
8976     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
8977     if (same)
8978       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
8979     else {
8980       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
8981       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
8982     }
8983     break;
8984
8985   case 2:
8986     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
8987     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
8988     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
8989     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
8990     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
8991     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
8992     break;
8993
8994   case 3:
8995     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
8996     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
8997     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
8998     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
8999     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
9000     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9001     break;
9002
9003   case 4:
9004     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9005     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
9006     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
9007     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
9008     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9009     break;
9010
9011   case 5:
9012     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9013     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9014     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
9015     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
9016     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
9017     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9018     break;
9019
9020   case 6:
9021     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9022     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9023     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
9024     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
9025     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
9026     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9027     break;
9028
9029   case 7:
9030     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9031     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
9032     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9033     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9034     break;
9035
9036   default:
9037     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
9038     break;
9039   }
9040 }
9041
9042 /*-----------------------------------------------------------------*/
9043 /* shiftR1Left2Result - shift right one byte from left to result   */
9044 /*-----------------------------------------------------------------*/
9045 static void shiftR1Left2Result (operand *left, int offl,
9046                                 operand *result, int offr,
9047                                 int shCount, int sign)
9048 {
9049   int same;
9050
9051   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9052   assert ((shCount >= 0) && (shCount <= 8));
9053
9054   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9055
9056   /* Copy the msb into the carry if signed. */
9057   if (sign) {
9058     shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
9059     return;
9060   }
9061
9062   /* Do NOT use result for intermediate results, it might be an SFR!. */
9063   switch (shCount) {
9064   case 0:
9065     if (!same) {
9066       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
9067       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9068     }
9069     break;
9070
9071   case 1:
9072     if (same) {
9073       emitCLRC;
9074       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
9075     } else {
9076       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9077       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
9078       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9079     }
9080     break;
9081
9082   case 2:
9083     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9084     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9085     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
9086     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9087     break;
9088
9089   case 3:
9090     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9091     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9092     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9093     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9094     break;
9095
9096   case 4:
9097     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9098     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9099     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9100     break;
9101
9102   case 5:
9103     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9104     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9105     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
9106     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9107     break;
9108
9109   case 6:
9110     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9111     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9112     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
9113     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9114     break;
9115
9116   case 7:
9117     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9118     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
9119     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9120     break;
9121
9122   default:
9123     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
9124     break;
9125   }
9126 }
9127
9128 /*-----------------------------------------------------------------*/
9129 /* shiftL1Left2Result - shift left one byte from left to result    */
9130 /*-----------------------------------------------------------------*/
9131 static void shiftL1Left2Result (operand *left, int offl,
9132                                 operand *result, int offr, int shCount)
9133 {
9134   int same;
9135
9136   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9137   assert ((shCount >= 0) && (shCount <= 8));
9138
9139   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9140
9141   /* Do NOT use result for intermediate results, it might be an SFR!. */
9142   switch (shCount) {
9143   case 0:
9144     if (!same) {
9145       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
9146       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9147     }
9148     break;
9149
9150   case 1:
9151     if (same) {
9152       emitCLRC;
9153       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
9154     } else {
9155       pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9156       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
9157       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9158     }
9159     break;
9160
9161   case 2:
9162     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
9163     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9164     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
9165     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9166     break;
9167
9168   case 3:
9169     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9170     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9171     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
9172     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9173     break;
9174
9175   case 4:
9176     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9177     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9178     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9179     break;
9180
9181   case 5:
9182     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
9183     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9184     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
9185     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9186     break;
9187
9188   case 6:
9189     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9190     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
9191     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
9192     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9193     break;
9194
9195   case 7:
9196     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
9197     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
9198     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
9199     break;
9200
9201   default:
9202     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
9203     break;
9204   }
9205 }
9206
9207 /*-----------------------------------------------------------------*/
9208 /* movLeft2Result - move byte from left to result                  */
9209 /*-----------------------------------------------------------------*/
9210 static void movLeft2Result (operand *left, int offl,
9211                             operand *result, int offr)
9212 {
9213   char *l;
9214   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9215   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9216     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9217
9218     if (*l == '@' && (IS_AOP_PREG(result))) {
9219       pic16_emitcode("mov","a,%s",l);
9220       pic16_aopPut(AOP(result),"a",offr);
9221     } else {
9222       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9223       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9224     }
9225   }
9226 }
9227
9228 /*-----------------------------------------------------------------*/
9229 /* shiftL2Left2Result - shift left two bytes from left to result   */
9230 /*-----------------------------------------------------------------*/
9231 static void shiftL2Left2Result (operand *left, int offl,
9232                                 operand *result, int offr, int shCount)
9233 {
9234   int same = pic16_sameRegs(AOP(result), AOP(left));
9235   int i;
9236
9237   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9238
9239   if (same && (offl != offr)) { // shift bytes
9240     if (offr > offl) {
9241        for(i=1;i>-1;i--) {
9242          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9243          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9244        }
9245     } else { // just treat as different later on
9246                 same = 0;
9247     }
9248   }
9249
9250   if(same) {
9251     switch(shCount) {
9252     case 0:
9253       break;
9254     case 1:
9255     case 2:
9256     case 3:
9257
9258       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9259       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9260       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9261
9262       while(--shCount) {
9263                 emitCLRC;
9264                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9265                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9266       }
9267
9268       break;
9269     case 4:
9270     case 5:
9271       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9272       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9273       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9274       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9275       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9276       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9277       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9278       if(shCount >=5) {
9279                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9280                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9281       }
9282       break;
9283     case 6:
9284       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9285       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9286       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9287       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9288       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9289       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9290       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9291       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9292       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9293       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9294       break;
9295     case 7:
9296       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9297       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9298       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9299       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9300       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9301     }
9302
9303   } else {
9304     switch(shCount) {
9305     case 0:
9306       break;
9307     case 1:
9308     case 2:
9309     case 3:
9310       /* note, use a mov/add for the shift since the mov has a
9311          chance of getting optimized out */
9312       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9313       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9314       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9315       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9316       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9317
9318       while(--shCount) {
9319                 emitCLRC;
9320                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9321                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9322       }
9323       break;
9324
9325     case 4:
9326     case 5:
9327       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9328       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9329       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9330       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9331       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9332       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9333       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9334       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9335
9336
9337       if(shCount == 5) {
9338                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9339                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9340       }
9341       break;
9342     case 6:
9343       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9344       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9345       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9346       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9347
9348       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9349       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9350       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9351       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9352       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9353       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9354       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9355       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9356       break;
9357     case 7:
9358       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9359       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9360       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9361       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9362       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9363     }
9364   }
9365
9366 }
9367 /*-----------------------------------------------------------------*/
9368 /* shiftR2Left2Result - shift right two bytes from left to result  */
9369 /*-----------------------------------------------------------------*/
9370 static void shiftR2Left2Result (operand *left, int offl,
9371                                 operand *result, int offr,
9372                                 int shCount, int sign)
9373 {
9374   int same = pic16_sameRegs(AOP(result), AOP(left));
9375   int i;
9376   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9377
9378   if (same && (offl != offr)) { // shift right bytes
9379     if (offr < offl) {
9380        for(i=0;i<2;i++) {
9381          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9382          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9383        }
9384     } else { // just treat as different later on
9385                 same = 0;
9386     }
9387   }
9388
9389   switch(shCount) {
9390   case 0:
9391     break;
9392   case 1:
9393   case 2:
9394   case 3:
9395     /* obtain sign from left operand */
9396     if(sign)
9397       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9398     else
9399       emitCLRC;
9400
9401     if(same) {
9402       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9403       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9404     } else {
9405       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9406       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9407       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9408       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9409     }
9410
9411     while(--shCount) {
9412       if(sign)
9413         /* now get sign from already assigned result (avoid BANKSEL) */
9414         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9415       else
9416         emitCLRC;
9417       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9418       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9419     }
9420     break;
9421   case 4:
9422   case 5:
9423     if(same) {
9424
9425       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9426       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9427       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9428
9429       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9430       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9431       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9432       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9433     } else {
9434       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9435       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9436       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9437
9438       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9439       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9440       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9441       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9442       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9443     }
9444
9445     if(shCount >=5) {
9446       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9447       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9448     }
9449
9450     if(sign) {
9451       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9452       pic16_emitpcode(POC_BTFSC,
9453                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9454       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9455     }
9456
9457     break;
9458
9459   case 6:
9460     if(same) {
9461
9462       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9463       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9464
9465       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9466       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9467       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9468       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9469       if(sign) {
9470         pic16_emitpcode(POC_BTFSC,
9471                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9472         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9473       }
9474       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9475       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9476       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9477       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9478     } else {
9479       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9480       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9481       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9482       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9483       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9484       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9485       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9486       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9487       if(sign) {
9488         pic16_emitpcode(POC_BTFSC,
9489                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9490         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9491       }
9492       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9493       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9494
9495
9496     }
9497
9498     break;
9499   case 7:
9500     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9501     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9502     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9503     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9504     if(sign) {
9505       emitSKPNC;
9506       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9507     } else
9508       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9509   }
9510 }
9511
9512
9513 /*-----------------------------------------------------------------*/
9514 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9515 /*-----------------------------------------------------------------*/
9516 static void shiftLLeftOrResult (operand *left, int offl,
9517                                 operand *result, int offr, int shCount)
9518 {
9519     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9520
9521     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9522     /* shift left accumulator */
9523     AccLsh(shCount, 1);
9524     /* or with result */
9525     /* back to result */
9526     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9527 }
9528
9529 /*-----------------------------------------------------------------*/
9530 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9531 /*-----------------------------------------------------------------*/
9532 static void shiftRLeftOrResult (operand *left, int offl,
9533                                 operand *result, int offr, int shCount)
9534 {
9535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9536
9537     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9538     /* shift right accumulator */
9539     AccRsh(shCount, 1);
9540     /* or with result */
9541     /* back to result */
9542     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9543 }
9544
9545 /*-----------------------------------------------------------------*/
9546 /* genlshOne - left shift a one byte quantity by known count       */
9547 /*-----------------------------------------------------------------*/
9548 static void genlshOne (operand *result, operand *left, int shCount)
9549 {
9550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9551     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9552 }
9553
9554 /*-----------------------------------------------------------------*/
9555 /* genlshTwo - left shift two bytes by known amount != 0           */
9556 /*-----------------------------------------------------------------*/
9557 static void genlshTwo (operand *result,operand *left, int shCount)
9558 {
9559     int size;
9560
9561     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9562     size = pic16_getDataSize(result);
9563
9564     /* if shCount >= 8 */
9565     if (shCount >= 8) {
9566         shCount -= 8 ;
9567
9568         if (size > 1){
9569             if (shCount)
9570                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9571             else
9572                 movLeft2Result(left, LSB, result, MSB16);
9573         }
9574         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9575     }
9576
9577     /*  1 <= shCount <= 7 */
9578     else {
9579         if(size == 1)
9580             shiftL1Left2Result(left, LSB, result, LSB, shCount);
9581         else
9582             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9583     }
9584 }
9585
9586 /*-----------------------------------------------------------------*/
9587 /* shiftLLong - shift left one long from left to result            */
9588 /* offr = LSB or MSB16                                             */
9589 /*-----------------------------------------------------------------*/
9590 static void shiftLLong (operand *left, operand *result, int offr )
9591 {
9592     int size = AOP_SIZE(result);
9593     int same = pic16_sameRegs(AOP(left),AOP(result));
9594         int i;
9595
9596     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9597
9598         if (same && (offr == MSB16)) { //shift one byte
9599                 for(i=size-1;i>=MSB16;i--) {
9600                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9601                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9602                 }
9603         } else {
9604                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9605         }
9606
9607     if (size > LSB+offr ){
9608                 if (same) {
9609                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9610                 } else {
9611                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9612                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9613                 }
9614          }
9615
9616     if(size > MSB16+offr){
9617                 if (same) {
9618                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9619                 } else {
9620                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9621                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9622                 }
9623     }
9624
9625     if(size > MSB24+offr){
9626                 if (same) {
9627                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9628                 } else {
9629                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9630                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9631                 }
9632     }
9633
9634     if(size > MSB32+offr){
9635                 if (same) {
9636                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9637                 } else {
9638                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9639                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9640                 }
9641     }
9642     if(offr != LSB)
9643                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9644
9645 }
9646
9647 /*-----------------------------------------------------------------*/
9648 /* genlshFour - shift four byte by a known amount != 0             */
9649 /*-----------------------------------------------------------------*/
9650 static void genlshFour (operand *result, operand *left, int shCount)
9651 {
9652     int size;
9653
9654     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9655     size = AOP_SIZE(result);
9656
9657     /* if shifting more that 3 bytes */
9658     if (shCount >= 24 ) {
9659         shCount -= 24;
9660         if (shCount)
9661             /* lowest order of left goes to the highest
9662             order of the destination */
9663             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9664         else
9665             movLeft2Result(left, LSB, result, MSB32);
9666
9667                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9668                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9669                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9670
9671         return;
9672     }
9673
9674     /* more than two bytes */
9675     else if ( shCount >= 16 ) {
9676         /* lower order two bytes goes to higher order two bytes */
9677         shCount -= 16;
9678         /* if some more remaining */
9679         if (shCount)
9680             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9681         else {
9682             movLeft2Result(left, MSB16, result, MSB32);
9683             movLeft2Result(left, LSB, result, MSB24);
9684         }
9685                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9686                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9687         return;
9688     }
9689
9690     /* if more than 1 byte */
9691     else if ( shCount >= 8 ) {
9692         /* lower order three bytes goes to higher order  three bytes */
9693         shCount -= 8;
9694         if(size == 2){
9695             if(shCount)
9696                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9697             else
9698                 movLeft2Result(left, LSB, result, MSB16);
9699         }
9700         else{   /* size = 4 */
9701             if(shCount == 0){
9702                 movLeft2Result(left, MSB24, result, MSB32);
9703                 movLeft2Result(left, MSB16, result, MSB24);
9704                 movLeft2Result(left, LSB, result, MSB16);
9705                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9706             }
9707             else if(shCount == 1)
9708                 shiftLLong(left, result, MSB16);
9709             else{
9710                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9711                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9712                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9713                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9714             }
9715         }
9716     }
9717
9718     /* 1 <= shCount <= 7 */
9719     else if(shCount <= 3)
9720     {
9721         shiftLLong(left, result, LSB);
9722         while(--shCount >= 1)
9723             shiftLLong(result, result, LSB);
9724     }
9725     /* 3 <= shCount <= 7, optimize */
9726     else{
9727         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9728         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9729         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9730     }
9731 }
9732
9733 /*-----------------------------------------------------------------*/
9734 /* genLeftShiftLiteral - left shifting by known count              */
9735 /*-----------------------------------------------------------------*/
9736 void pic16_genLeftShiftLiteral (operand *left,
9737                                  operand *right,
9738                                  operand *result,
9739                                  iCode *ic)
9740 {
9741     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
9742     int size;
9743
9744     FENTRY;
9745     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9746     pic16_freeAsmop(right,NULL,ic,TRUE);
9747
9748     pic16_aopOp(left,ic,FALSE);
9749     pic16_aopOp(result,ic,TRUE);
9750
9751     size = getSize(operandType(result));
9752
9753 #if VIEW_SIZE
9754     pic16_emitcode("; shift left ","result %d, left %d",size,
9755              AOP_SIZE(left));
9756 #endif
9757
9758     /* I suppose that the left size >= result size */
9759     if(shCount == 0){
9760         while(size--){
9761             movLeft2Result(left, size, result, size);
9762         }
9763     }
9764
9765     else if(shCount >= (size * 8))
9766         while(size--)
9767             pic16_aopPut(AOP(result),zero,size);
9768     else{
9769         switch (size) {
9770             case 1:
9771                 genlshOne (result,left,shCount);
9772                 break;
9773
9774             case 2:
9775             case 3:
9776                 genlshTwo (result,left,shCount);
9777                 break;
9778
9779             case 4:
9780                 genlshFour (result,left,shCount);
9781                 break;
9782         }
9783     }
9784     pic16_freeAsmop(left,NULL,ic,TRUE);
9785     pic16_freeAsmop(result,NULL,ic,TRUE);
9786 }
9787
9788 /*-----------------------------------------------------------------*
9789  * genMultiAsm - repeat assembly instruction for size of register.
9790  * if endian == 1, then the high byte (i.e base address + size of
9791  * register) is used first else the low byte is used first;
9792  *-----------------------------------------------------------------*/
9793 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9794 {
9795
9796   int offset = 0;
9797
9798   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9799
9800   if(!reg)
9801     return;
9802
9803   if(!endian) {
9804     endian = 1;
9805   } else {
9806     endian = -1;
9807     offset = size-1;
9808   }
9809
9810   while(size--) {
9811     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9812     offset += endian;
9813   }
9814
9815 }
9816
9817 #if !(USE_GENERIC_SIGNED_SHIFT)
9818 /*-----------------------------------------------------------------*/
9819 /* genLeftShift - generates code for left shifting                 */
9820 /*-----------------------------------------------------------------*/
9821 static void genLeftShift (iCode *ic)
9822 {
9823   operand *left,*right, *result;
9824   int size, offset;
9825 //  char *l;
9826   symbol *tlbl , *tlbl1;
9827   pCodeOp *pctemp;
9828
9829   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9830
9831   right = IC_RIGHT(ic);
9832   left  = IC_LEFT(ic);
9833   result = IC_RESULT(ic);
9834
9835   pic16_aopOp(right,ic,FALSE);
9836
9837   /* if the shift count is known then do it
9838      as efficiently as possible */
9839   if (AOP_TYPE(right) == AOP_LIT) {
9840     pic16_genLeftShiftLiteral (left,right,result,ic);
9841     return ;
9842   }
9843
9844   /* shift count is unknown then we have to form
9845    * a loop. Get the loop count in WREG : Note: we take
9846    * only the lower order byte since shifting
9847    * more than 32 bits make no sense anyway, ( the
9848    * largest size of an object can be only 32 bits ) */
9849
9850   pic16_aopOp(left,ic,FALSE);
9851   pic16_aopOp(result,ic,FALSE);
9852
9853   /* now move the left to the result if they are not the
9854    * same, and if size > 1,
9855    * and if right is not same to result (!!!) -- VR */
9856   if (!pic16_sameRegs(AOP(left),AOP(result))
9857       && (AOP_SIZE(result) > 1)) {
9858
9859     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9860
9861     size = AOP_SIZE(result);
9862     offset=0;
9863     while (size--) {
9864
9865 #if 0
9866       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9867       if (*l == '@' && (IS_AOP_PREG(result))) {
9868
9869           pic16_emitcode("mov","a,%s",l);
9870           pic16_aopPut(AOP(result),"a",offset);
9871       } else
9872 #endif
9873       {
9874         /* we don't know if left is a literal or a register, take care -- VR */
9875         pic16_mov2f(AOP(result), AOP(left), offset);
9876       }
9877       offset++;
9878     }
9879   }
9880
9881   size = AOP_SIZE(result);
9882
9883   /* if it is only one byte then */
9884   if (size == 1) {
9885     if(optimized_for_speed) {
9886       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9887       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9888       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9889       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9890       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9891       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9892       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9893       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9894       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9895       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9896       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9897       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9898     } else {
9899
9900       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9901
9902       tlbl = newiTempLabel(NULL);
9903
9904 #if 1
9905       /* this is already done, why change it? */
9906       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9907                 pic16_mov2f(AOP(result), AOP(left), 0);
9908       }
9909 #endif
9910
9911       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9912       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9913       pic16_emitpLabel(tlbl->key);
9914       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9915       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9916       emitSKPC;
9917       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9918     }
9919     goto release ;
9920   }
9921
9922   if (pic16_sameRegs(AOP(left),AOP(result))) {
9923
9924     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9925
9926     tlbl = newiTempLabel(NULL);
9927     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9928     genMultiAsm(POC_RRCF, result, size,1);
9929     pic16_emitpLabel(tlbl->key);
9930     genMultiAsm(POC_RLCF, result, size,0);
9931     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9932     emitSKPC;
9933     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9934     goto release;
9935   }
9936
9937   //tlbl = newiTempLabel(NULL);
9938   //offset = 0 ;
9939   //tlbl1 = newiTempLabel(NULL);
9940
9941   //reAdjustPreg(AOP(result));
9942
9943   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9944   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9945   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9946   //MOVA(l);
9947   //pic16_emitcode("add","a,acc");
9948   //pic16_aopPut(AOP(result),"a",offset++);
9949   //while (--size) {
9950   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9951   //  MOVA(l);
9952   //  pic16_emitcode("rlc","a");
9953   //  pic16_aopPut(AOP(result),"a",offset++);
9954   //}
9955   //reAdjustPreg(AOP(result));
9956
9957   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9958   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9959
9960
9961   tlbl = newiTempLabel(NULL);
9962   tlbl1= newiTempLabel(NULL);
9963
9964   size = AOP_SIZE(result);
9965   offset = 1;
9966
9967   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9968
9969   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9970
9971   /* offset should be 0, 1 or 3 */
9972
9973   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9974   emitSKPNZ;
9975   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9976
9977   pic16_emitpcode(POC_MOVWF, pctemp);
9978
9979
9980   pic16_emitpLabel(tlbl->key);
9981
9982   emitCLRC;
9983   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9984   while(--size)
9985     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9986
9987   pic16_emitpcode(POC_DECFSZ,  pctemp);
9988   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9989   pic16_emitpLabel(tlbl1->key);
9990
9991   pic16_popReleaseTempReg(pctemp,1);
9992
9993
9994  release:
9995   pic16_freeAsmop (right,NULL,ic,TRUE);
9996   pic16_freeAsmop(left,NULL,ic,TRUE);
9997   pic16_freeAsmop(result,NULL,ic,TRUE);
9998 }
9999 #endif
10000
10001
10002 #if 0
10003 #error old code (left here for reference)
10004 /*-----------------------------------------------------------------*/
10005 /* genLeftShift - generates code for left shifting                 */
10006 /*-----------------------------------------------------------------*/
10007 static void genLeftShift (iCode *ic)
10008 {
10009   operand *left,*right, *result;
10010   int size, offset;
10011   char *l;
10012   symbol *tlbl , *tlbl1;
10013   pCodeOp *pctemp;
10014
10015   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10016
10017   right = IC_RIGHT(ic);
10018   left  = IC_LEFT(ic);
10019   result = IC_RESULT(ic);
10020
10021   pic16_aopOp(right,ic,FALSE);
10022
10023   /* if the shift count is known then do it
10024      as efficiently as possible */
10025   if (AOP_TYPE(right) == AOP_LIT) {
10026     pic16_genLeftShiftLiteral (left,right,result,ic);
10027     return ;
10028   }
10029
10030   /* shift count is unknown then we have to form
10031      a loop get the loop count in B : Note: we take
10032      only the lower order byte since shifting
10033      more that 32 bits make no sense anyway, ( the
10034      largest size of an object can be only 32 bits ) */
10035
10036
10037   pic16_aopOp(left,ic,FALSE);
10038   pic16_aopOp(result,ic,FALSE);
10039
10040   /* now move the left to the result if they are not the
10041      same */
10042   if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10043       AOP_SIZE(result) > 1) {
10044
10045     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10046
10047     size = AOP_SIZE(result);
10048     offset=0;
10049     while (size--) {
10050       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10051       if (*l == '@' && (IS_AOP_PREG(result))) {
10052
10053         pic16_emitcode("mov","a,%s",l);
10054         pic16_aopPut(AOP(result),"a",offset);
10055       } else {
10056
10057         /* we don't know if left is a literal or a register, take care -- VR */
10058         pic16_mov2f(AOP(result), AOP(left), offset);
10059       }
10060       offset++;
10061     }
10062   }
10063
10064   size = AOP_SIZE(result);
10065
10066   /* if it is only one byte then */
10067   if (size == 1) {
10068     if(optimized_for_speed) {
10069       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10070       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10071       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10072       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10073       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10074       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10075       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10076       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10077       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10078       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10079       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10080       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10081     } else {
10082
10083       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10084
10085       tlbl = newiTempLabel(NULL);
10086       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10087                 pic16_mov2f(AOP(result), AOP(left), 0);
10088
10089 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10090 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10091       }
10092
10093       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10094       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10095       pic16_emitpLabel(tlbl->key);
10096       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10097       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10098       emitSKPC;
10099       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10100     }
10101     goto release ;
10102   }
10103
10104   if (pic16_sameRegs(AOP(left),AOP(result))) {
10105
10106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10107
10108     tlbl = newiTempLabel(NULL);
10109     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10110     genMultiAsm(POC_RRCF, result, size,1);
10111     pic16_emitpLabel(tlbl->key);
10112     genMultiAsm(POC_RLCF, result, size,0);
10113     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10114     emitSKPC;
10115     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10116     goto release;
10117   }
10118
10119   //tlbl = newiTempLabel(NULL);
10120   //offset = 0 ;
10121   //tlbl1 = newiTempLabel(NULL);
10122
10123   //reAdjustPreg(AOP(result));
10124
10125   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10126   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10127   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10128   //MOVA(l);
10129   //pic16_emitcode("add","a,acc");
10130   //pic16_aopPut(AOP(result),"a",offset++);
10131   //while (--size) {
10132   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10133   //  MOVA(l);
10134   //  pic16_emitcode("rlc","a");
10135   //  pic16_aopPut(AOP(result),"a",offset++);
10136   //}
10137   //reAdjustPreg(AOP(result));
10138
10139   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10140   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10141
10142
10143   tlbl = newiTempLabel(NULL);
10144   tlbl1= newiTempLabel(NULL);
10145
10146   size = AOP_SIZE(result);
10147   offset = 1;
10148
10149   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10150
10151   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10152
10153   /* offset should be 0, 1 or 3 */
10154
10155   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10156   emitSKPNZ;
10157   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10158
10159   pic16_emitpcode(POC_MOVWF, pctemp);
10160
10161
10162   pic16_emitpLabel(tlbl->key);
10163
10164   emitCLRC;
10165   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10166   while(--size)
10167     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10168
10169   pic16_emitpcode(POC_DECFSZ,  pctemp);
10170   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10171   pic16_emitpLabel(tlbl1->key);
10172
10173   pic16_popReleaseTempReg(pctemp,1);
10174
10175
10176  release:
10177   pic16_freeAsmop (right,NULL,ic,TRUE);
10178   pic16_freeAsmop(left,NULL,ic,TRUE);
10179   pic16_freeAsmop(result,NULL,ic,TRUE);
10180 }
10181 #endif
10182
10183 /*-----------------------------------------------------------------*/
10184 /* genrshOne - right shift a one byte quantity by known count      */
10185 /*-----------------------------------------------------------------*/
10186 static void genrshOne (operand *result, operand *left,
10187                        int shCount, int sign)
10188 {
10189     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10190     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10191 }
10192
10193 /*-----------------------------------------------------------------*/
10194 /* genrshTwo - right shift two bytes by known amount != 0          */
10195 /*-----------------------------------------------------------------*/
10196 static void genrshTwo (operand *result,operand *left,
10197                        int shCount, int sign)
10198 {
10199   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10200   /* if shCount >= 8 */
10201   if (shCount >= 8) {
10202     shCount -= 8 ;
10203     if (shCount)
10204       shiftR1Left2Result(left, MSB16, result, LSB,
10205                          shCount, sign);
10206     else
10207       movLeft2Result(left, MSB16, result, LSB);
10208
10209     pic16_addSign (result, 1, sign);
10210   }
10211
10212   /*  1 <= shCount <= 7 */
10213   else
10214     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10215 }
10216
10217 /*-----------------------------------------------------------------*/
10218 /* shiftRLong - shift right one long from left to result           */
10219 /* offl = LSB or MSB16                                             */
10220 /*-----------------------------------------------------------------*/
10221 static void shiftRLong (operand *left, int offl,
10222                         operand *result, int sign)
10223 {
10224     int size = AOP_SIZE(result);
10225     int same = pic16_sameRegs(AOP(left),AOP(result));
10226     int i;
10227     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10228
10229         if (same && (offl == MSB16)) { //shift one byte right
10230                 for(i=MSB16;i<size;i++) {
10231                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10232                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10233                 }
10234         }
10235
10236     if(sign)
10237                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10238         else
10239                 emitCLRC;
10240
10241         if (same) {
10242                 if (offl == LSB)
10243                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10244         } else {
10245         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10246         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10247         }
10248
10249     if(offl == MSB16) {
10250         /* add sign of "a" */
10251         pic16_addSign(result, MSB32, sign);
10252         }
10253
10254         if (same) {
10255         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10256         } else {
10257         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10258         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10259         }
10260
10261         if (same) {
10262         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10263         } else {
10264         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10265         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10266         }
10267
10268         if (same) {
10269         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10270         } else {
10271         if(offl == LSB){
10272                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10273                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10274         }
10275         }
10276 }
10277
10278 /*-----------------------------------------------------------------*/
10279 /* genrshFour - shift four byte by a known amount != 0             */
10280 /*-----------------------------------------------------------------*/
10281 static void genrshFour (operand *result, operand *left,
10282                         int shCount, int sign)
10283 {
10284   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10285   /* if shifting more that 3 bytes */
10286   if(shCount >= 24 ) {
10287     shCount -= 24;
10288     if(shCount)
10289       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10290     else
10291       movLeft2Result(left, MSB32, result, LSB);
10292
10293     pic16_addSign(result, MSB16, sign);
10294   }
10295   else if(shCount >= 16){
10296     shCount -= 16;
10297     if(shCount)
10298       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10299     else{
10300       movLeft2Result(left, MSB24, result, LSB);
10301       movLeft2Result(left, MSB32, result, MSB16);
10302     }
10303     pic16_addSign(result, MSB24, sign);
10304   }
10305   else if(shCount >= 8){
10306     shCount -= 8;
10307     if(shCount == 1)
10308       shiftRLong(left, MSB16, result, sign);
10309     else if(shCount == 0){
10310       movLeft2Result(left, MSB16, result, LSB);
10311       movLeft2Result(left, MSB24, result, MSB16);
10312       movLeft2Result(left, MSB32, result, MSB24);
10313       pic16_addSign(result, MSB32, sign);
10314     }
10315     else{ //shcount >= 2
10316       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10317       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10318       /* the last shift is signed */
10319       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10320       pic16_addSign(result, MSB32, sign);
10321     }
10322   }
10323   else{   /* 1 <= shCount <= 7 */
10324     if(shCount <= 2){
10325       shiftRLong(left, LSB, result, sign);
10326       if(shCount == 2)
10327         shiftRLong(result, LSB, result, sign);
10328     }
10329     else{
10330       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10331       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10332       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10333     }
10334   }
10335 }
10336
10337 /*-----------------------------------------------------------------*/
10338 /* genRightShiftLiteral - right shifting by known count            */
10339 /*-----------------------------------------------------------------*/
10340 static void genRightShiftLiteral (operand *left,
10341                                   operand *right,
10342                                   operand *result,
10343                                   iCode *ic,
10344                                   int sign)
10345 {
10346   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
10347   int lsize,res_size;
10348
10349   pic16_freeAsmop(right,NULL,ic,TRUE);
10350
10351   pic16_aopOp(left,ic,FALSE);
10352   pic16_aopOp(result,ic,TRUE);
10353
10354   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10355
10356 #if VIEW_SIZE
10357   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10358                  AOP_SIZE(left));
10359 #endif
10360
10361   lsize = pic16_getDataSize(left);
10362   res_size = pic16_getDataSize(result);
10363   /* test the LEFT size !!! */
10364
10365   /* I suppose that the left size >= result size */
10366   if (shCount == 0) {
10367     assert (res_size <= lsize);
10368     while (res_size--) {
10369       pic16_mov2f (AOP(result), AOP(left), res_size);
10370     } // for
10371   } else if (shCount >= (lsize * 8)) {
10372     if (sign) {
10373       /* 
10374        * Do NOT use
10375        *    CLRF    result
10376        *    BTFSC   left, 7
10377        *    SETF    result
10378        * even for 8-bit operands; result might be an SFR.
10379        */
10380       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
10381       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
10382       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10383       while (res_size--) {
10384         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
10385       }
10386     } else { // unsigned
10387       while (res_size--) {
10388         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
10389       }
10390     }
10391   } else { // 0 < shCount < 8*lsize
10392     switch (res_size) {
10393     case 1:
10394       genrshOne (result,left,shCount,sign);
10395       break;
10396
10397     case 2:
10398       genrshTwo (result,left,shCount,sign);
10399       break;
10400
10401     case 4:
10402       genrshFour (result,left,shCount,sign);
10403       break;
10404     default :
10405       break;
10406     }
10407   }
10408
10409   pic16_freeAsmop(left,NULL,ic,TRUE);
10410   pic16_freeAsmop(result,NULL,ic,TRUE);
10411 }
10412
10413 #if !(USE_GENERIC_SIGNED_SHIFT)
10414 /*-----------------------------------------------------------------*/
10415 /* genSignedRightShift - right shift of signed number              */
10416 /*-----------------------------------------------------------------*/
10417 static void genSignedRightShift (iCode *ic)
10418 {
10419   operand *right, *left, *result;
10420   int size, offset;
10421   //  char *l;
10422   symbol *tlbl, *tlbl1 ;
10423   pCodeOp *pctemp;
10424
10425   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10426
10427   /* we do it the hard way put the shift count in b
10428      and loop thru preserving the sign */
10429   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10430
10431   right = IC_RIGHT(ic);
10432   left  = IC_LEFT(ic);
10433   result = IC_RESULT(ic);
10434
10435   pic16_aopOp(right,ic,FALSE);
10436   pic16_aopOp(left,ic,FALSE);
10437   pic16_aopOp(result,ic,FALSE);
10438
10439
10440   if ( AOP_TYPE(right) == AOP_LIT) {
10441     genRightShiftLiteral (left,right,result,ic,1);
10442     return ;
10443   }
10444   /* shift count is unknown then we have to form
10445      a loop get the loop count in B : Note: we take
10446      only the lower order byte since shifting
10447      more that 32 bits make no sense anyway, ( the
10448      largest size of an object can be only 32 bits ) */
10449
10450   /* now move the left to the result if they are not the
10451      same */
10452   if (!pic16_sameRegs(AOP(left), AOP(result))
10453       && AOP_SIZE(result) > 1)
10454   {
10455     size = AOP_SIZE(result);
10456     offset = 0;
10457     while (size--) {
10458       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
10459       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10460       offset++;
10461     }
10462   }
10463
10464   /* mov the highest order bit to OVR */
10465   tlbl = newiTempLabel(NULL);
10466   tlbl1= newiTempLabel(NULL);
10467
10468   size = AOP_SIZE(result);
10469   offset = size - 1;
10470
10471   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10472
10473   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10474
10475   /* offset should be 0, 1 or 3 */
10476   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10477   emitSKPNZ;
10478   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10479
10480   pic16_emitpcode(POC_MOVWF, pctemp);
10481
10482
10483   pic16_emitpLabel(tlbl->key);
10484
10485   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10486   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10487
10488   while(--size) {
10489     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10490   }
10491
10492   pic16_emitpcode(POC_DECFSZ,  pctemp);
10493   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10494   pic16_emitpLabel(tlbl1->key);
10495
10496   pic16_popReleaseTempReg(pctemp,1);
10497
10498   pic16_freeAsmop(left,NULL,ic,TRUE);
10499   pic16_freeAsmop(result,NULL,ic,TRUE);
10500   pic16_freeAsmop(right,NULL,ic,TRUE);
10501 }
10502 #endif
10503
10504 #if !(USE_GENERIC_SIGNED_SHIFT)
10505 #warning This implementation of genRightShift() is incomplete!
10506 /*-----------------------------------------------------------------*/
10507 /* genRightShift - generate code for right shifting                */
10508 /*-----------------------------------------------------------------*/
10509 static void genRightShift (iCode *ic)
10510 {
10511     operand *right, *left, *result;
10512     sym_link *letype ;
10513     int size, offset;
10514     char *l;
10515     symbol *tlbl, *tlbl1 ;
10516
10517     /* if signed then we do it the hard way preserve the
10518     sign bit moving it inwards */
10519     letype = getSpec(operandType(IC_LEFT(ic)));
10520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10521
10522     if (!SPEC_USIGN(letype)) {
10523         genSignedRightShift (ic);
10524         return ;
10525     }
10526
10527     /* signed & unsigned types are treated the same : i.e. the
10528     signed is NOT propagated inwards : quoting from the
10529     ANSI - standard : "for E1 >> E2, is equivalent to division
10530     by 2**E2 if unsigned or if it has a non-negative value,
10531     otherwise the result is implementation defined ", MY definition
10532     is that the sign does not get propagated */
10533
10534     right = IC_RIGHT(ic);
10535     left  = IC_LEFT(ic);
10536     result = IC_RESULT(ic);
10537
10538     pic16_aopOp(right,ic,FALSE);
10539
10540     /* if the shift count is known then do it
10541     as efficiently as possible */
10542     if (AOP_TYPE(right) == AOP_LIT) {
10543         genRightShiftLiteral (left,right,result,ic, 0);
10544         return ;
10545     }
10546
10547     /* shift count is unknown then we have to form
10548     a loop get the loop count in B : Note: we take
10549     only the lower order byte since shifting
10550     more that 32 bits make no sense anyway, ( the
10551     largest size of an object can be only 32 bits ) */
10552
10553     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10554     pic16_emitcode("inc","b");
10555     pic16_aopOp(left,ic,FALSE);
10556     pic16_aopOp(result,ic,FALSE);
10557
10558     /* now move the left to the result if they are not the
10559     same */
10560     if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10561         AOP_SIZE(result) > 1) {
10562
10563         size = AOP_SIZE(result);
10564         offset=0;
10565         while (size--) {
10566             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10567             if (*l == '@' && IS_AOP_PREG(result)) {
10568
10569                 pic16_emitcode("mov","a,%s",l);
10570                 pic16_aopPut(AOP(result),"a",offset);
10571             } else
10572                 pic16_aopPut(AOP(result),l,offset);
10573             offset++;
10574         }
10575     }
10576
10577     tlbl = newiTempLabel(NULL);
10578     tlbl1= newiTempLabel(NULL);
10579     size = AOP_SIZE(result);
10580     offset = size - 1;
10581
10582     /* if it is only one byte then */
10583     if (size == 1) {
10584
10585       tlbl = newiTempLabel(NULL);
10586       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10587         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10588         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10589       }
10590
10591       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10592       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10593       pic16_emitpLabel(tlbl->key);
10594       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10595       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10596       emitSKPC;
10597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10598
10599       goto release ;
10600     }
10601
10602     reAdjustPreg(AOP(result));
10603     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10604     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10605     CLRC;
10606     while (size--) {
10607         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10608         MOVA(l);
10609         pic16_emitcode("rrc","a");
10610         pic16_aopPut(AOP(result),"a",offset--);
10611     }
10612     reAdjustPreg(AOP(result));
10613
10614     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10615     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10616
10617 release:
10618     pic16_freeAsmop(left,NULL,ic,TRUE);
10619     pic16_freeAsmop (right,NULL,ic,TRUE);
10620     pic16_freeAsmop(result,NULL,ic,TRUE);
10621 }
10622 #endif
10623
10624 #if (USE_GENERIC_SIGNED_SHIFT)
10625 /*-----------------------------------------------------------------*/
10626 /* genGenericShift - generates code for left or right shifting     */
10627 /*-----------------------------------------------------------------*/
10628 static void genGenericShift (iCode *ic, int isShiftLeft) {
10629   operand *left,*right, *result;
10630   int offset;
10631   int sign, signedCount;
10632   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10633   PIC_OPCODE pos_shift, neg_shift;
10634
10635   FENTRY;
10636
10637   right = IC_RIGHT(ic);
10638   left  = IC_LEFT(ic);
10639   result = IC_RESULT(ic);
10640
10641   pic16_aopOp(right,ic,FALSE);
10642   pic16_aopOp(left,ic,FALSE);
10643   pic16_aopOp(result,ic,TRUE);
10644
10645   sign = !SPEC_USIGN(operandType (left));
10646   signedCount = !SPEC_USIGN(operandType (right));
10647
10648   /* if the shift count is known then do it
10649      as efficiently as possible */
10650   if (AOP_TYPE(right) == AOP_LIT) {
10651     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
10652     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10653     // we should modify right->aopu.aop_lit here!
10654     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10655     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10656     if (isShiftLeft)
10657       pic16_genLeftShiftLiteral (left,right,result,ic);
10658     else
10659       genRightShiftLiteral (left,right,result,ic, sign);
10660
10661     goto release;
10662   } // if (right is literal)
10663
10664   /* shift count is unknown then we have to form a loop.
10665    * Note: we take only the lower order byte since shifting
10666    * more than 32 bits make no sense anyway, ( the
10667    * largest size of an object can be only 32 bits )
10668    * Note: we perform arithmetic shifts if the left operand is
10669    * signed and we do an (effective) right shift, i. e. we
10670    * shift in the sign bit from the left. */
10671
10672   label_complete = newiTempLabel ( NULL );
10673   label_loop_pos = newiTempLabel ( NULL );
10674   label_loop_neg = NULL;
10675   label_negative = NULL;
10676   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10677   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10678
10679   if (signedCount) {
10680     // additional labels needed
10681     label_loop_neg = newiTempLabel ( NULL );
10682     label_negative = newiTempLabel ( NULL );
10683   } // if
10684
10685   // copy source to result -- this will effectively truncate the left operand to the size of result!
10686   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10687   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10688   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10689     pic16_mov2f (AOP(result),AOP(left), offset);
10690   } // for
10691
10692   // if result is longer than left, fill with zeros (or sign)
10693   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10694     if (sign && AOP_SIZE(left) > 0) {
10695       // shift signed operand -- fill with sign
10696       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10697       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10698       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10699       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10700         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10701       } // for
10702     } else {
10703       // shift unsigned operand -- fill result with zeros
10704       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10705         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10706       } // for
10707     }
10708   } // if (size mismatch)
10709
10710   pic16_mov2w (AOP(right), 0);
10711   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10712   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10713
10714 #if 0
10715   // perform a shift by one (shift count is positive)
10716   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10717   // 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])
10718   pic16_emitpLabel (label_loop_pos->key);
10719   emitCLRC;
10720   if (sign && (pos_shift == POC_RRCF)) {
10721     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10722     emitSETC;
10723   } // if
10724   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10725   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10726   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10727 #else
10728   // perform a shift by one (shift count is positive)
10729   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10730   // 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])
10731   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10732   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10733   emitCLRC;
10734   pic16_emitpLabel (label_loop_pos->key);
10735   if (sign && (pos_shift == POC_RRCF)) {
10736     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10737     emitSETC;
10738   } // if
10739   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10740   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10741   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10742   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10743 #endif
10744
10745   if (signedCount) {
10746     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10747
10748     pic16_emitpLabel (label_negative->key);
10749     // perform a shift by -1 (shift count is negative)
10750     // 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)
10751     emitCLRC;
10752     pic16_emitpLabel (label_loop_neg->key);
10753     if (sign && (neg_shift == POC_RRCF)) {
10754       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10755       emitSETC;
10756     } // if
10757     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10758     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10759     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10760     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10761   } // if (signedCount)
10762
10763   pic16_emitpLabel (label_complete->key);
10764
10765 release:
10766   pic16_freeAsmop (right,NULL,ic,TRUE);
10767   pic16_freeAsmop(left,NULL,ic,TRUE);
10768   pic16_freeAsmop(result,NULL,ic,TRUE);
10769 }
10770
10771 static void genLeftShift (iCode *ic) {
10772   genGenericShift (ic, 1);
10773 }
10774
10775 static void genRightShift (iCode *ic) {
10776   genGenericShift (ic, 0);
10777 }
10778 #endif
10779
10780
10781 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10782 void pic16_loadFSR0(operand *op, int lit)
10783 {
10784   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10785     if (AOP_TYPE(op) == AOP_LIT) {
10786       /* handle 12 bit integers correctly */
10787       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
10788       if ((val & 0x0fff) != val) {
10789         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10790                 val, (val & 0x0fff) );
10791         val &= 0x0fff;
10792       }
10793       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10794     } else {
10795       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10796     }
10797   } else {
10798     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10799     // set up FSR0 with address of result
10800     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10801     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10802   }
10803 }
10804
10805 /*----------------------------------------------------------------*/
10806 /* pic16_derefPtr - move one byte from the location ptr points to */
10807 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10808 /*                  to the location ptr points to (doWrite != 0)   */
10809 /*----------------------------------------------------------------*/
10810 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10811 {
10812   if (!IS_PTR(operandType(ptr)))
10813   {
10814     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10815     else pic16_mov2w (AOP(ptr), 0);
10816     return;
10817   }
10818
10819   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10820   /* We might determine pointer type right here: */
10821   p_type = DCL_TYPE(operandType(ptr));
10822
10823   switch (p_type) {
10824     case FPOINTER:
10825     case POINTER:
10826       if (!fsr0_setup || !*fsr0_setup)
10827       {
10828         pic16_loadFSR0( ptr, 0 );
10829         if (fsr0_setup) *fsr0_setup = 1;
10830       }
10831       if (doWrite)
10832         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10833       else
10834         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10835       break;
10836
10837     case GPOINTER:
10838       if (AOP(ptr)->aopu.aop_reg[2]) {
10839         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10840         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10841         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10842         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10843         pic16_mov2w(AOP(ptr), 2);
10844         pic16_callGenericPointerRW(doWrite, 1);
10845       } else {
10846         // data pointer (just 2 byte given)
10847         if (!fsr0_setup || !*fsr0_setup)
10848         {
10849           pic16_loadFSR0( ptr, 0 );
10850           if (fsr0_setup) *fsr0_setup = 1;
10851         }
10852         if (doWrite)
10853           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10854         else
10855           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10856       }
10857       break;
10858
10859     default:
10860       assert (0 && "invalid pointer type specified");
10861       break;
10862   }
10863 }
10864
10865 /*-----------------------------------------------------------------*/
10866 /* genUnpackBits - generates code for unpacking bits               */
10867 /*-----------------------------------------------------------------*/
10868 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10869 {
10870   int shCnt ;
10871   sym_link *etype, *letype;
10872   int blen=0, bstr=0;
10873   int lbstr;
10874   int same;
10875   pCodeOp *op;
10876
10877   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10878   etype = getSpec(operandType(result));
10879   letype = getSpec(operandType(left));
10880
10881   //    if(IS_BITFIELD(etype)) {
10882   blen = SPEC_BLEN(etype);
10883   bstr = SPEC_BSTR(etype);
10884   //    }
10885
10886   lbstr = SPEC_BSTR( letype );
10887
10888   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10889       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10890
10891 #if 1
10892   if((blen == 1) && (bstr < 8)
10893       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10894     /* it is a single bit, so use the appropriate bit instructions */
10895     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10896
10897     same = pic16_sameRegs(AOP(left),AOP(result));
10898     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10899     pic16_emitpcode(POC_CLRF, op);
10900
10901     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10902       /* workaround to reduce the extra lfsr instruction */
10903       pic16_emitpcode(POC_BTFSC,
10904           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10905     } else {
10906       assert (PIC_IS_DATA_PTR (operandType(left)));
10907       pic16_loadFSR0 (left, 0);
10908       pic16_emitpcode(POC_BTFSC,
10909           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10910     }
10911
10912     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10913       /* unsigned bitfields result in either 0 or 1 */
10914       pic16_emitpcode(POC_INCF, op);
10915     } else {
10916       /* signed bitfields result in either 0 or -1 */
10917       pic16_emitpcode(POC_DECF, op);
10918     }
10919     if (same) {
10920       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10921     }
10922
10923     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10924     return;
10925   }
10926
10927 #endif
10928
10929   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10930     // access symbol directly
10931     pic16_mov2w (AOP(left), 0);
10932   } else {
10933     pic16_derefPtr (left, ptype, 0, NULL);
10934   }
10935
10936   /* if we have bitdisplacement then it fits   */
10937   /* into this byte completely or if length is */
10938   /* less than a byte                          */
10939   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10940
10941     /* shift right acc */
10942     AccRsh(shCnt, 0);
10943
10944     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10945           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10946
10947     /* VR -- normally I would use the following, but since we use the hack,
10948      * to avoid the masking from AccRsh, why not mask it right now? */
10949
10950     /*
10951        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10952      */
10953
10954     /* extend signed bitfields to 8 bits */
10955     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10956     {
10957       assert (blen + bstr > 0);
10958       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10959       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10960     }
10961
10962     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10963
10964     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10965     return ;
10966   }
10967
10968   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10969   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10970   exit(EXIT_FAILURE);
10971
10972   return ;
10973 }
10974
10975
10976 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10977 {
10978   int size, offset = 0, leoffset=0 ;
10979
10980         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10981         pic16_aopOp(result, ic, TRUE);
10982
10983         FENTRY;
10984
10985         size = AOP_SIZE(result);
10986 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10987
10988
10989 #if 1
10990         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10991                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10992                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10993                 goto release;
10994         }
10995 #endif
10996
10997         if(AOP(left)->aopu.pcop->type == PO_DIR)
10998                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10999
11000         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11001
11002         while (size--) {
11003                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11004
11005 //              pic16_DumpOp("(result)",result);
11006                 if(is_LitAOp(AOP(result))) {
11007                         pic16_mov2w(AOP(left), offset); // patch 8
11008                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11009                 } else {
11010                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11011                                 pic16_popGet(AOP(left), offset), //patch 8
11012                                 pic16_popGet(AOP(result), offset)));
11013                 }
11014
11015                 offset++;
11016                 leoffset++;
11017         }
11018
11019 release:
11020     pic16_freeAsmop(result,NULL,ic,TRUE);
11021 }
11022
11023
11024
11025 /*-----------------------------------------------------------------*/
11026 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11027 /*-----------------------------------------------------------------*/
11028 static void genNearPointerGet (operand *left,
11029                                operand *result,
11030                                iCode *ic)
11031 {
11032 //  asmop *aop = NULL;
11033   //regs *preg = NULL ;
11034   sym_link *rtype, *retype;
11035   sym_link *ltype, *letype;
11036
11037     FENTRY;
11038
11039     rtype = operandType(result);
11040     retype= getSpec(rtype);
11041     ltype = operandType(left);
11042     letype= getSpec(ltype);
11043
11044     pic16_aopOp(left,ic,FALSE);
11045
11046 //    pic16_DumpOp("(left)",left);
11047 //    pic16_DumpOp("(result)",result);
11048
11049     /* if left is rematerialisable and
11050      * result is not bit variable type and
11051      * the left is pointer to data space i.e
11052      * lower 128 bytes of space */
11053
11054     if (AOP_TYPE(left) == AOP_PCODE
11055       && !IS_BITFIELD(retype)
11056       && DCL_TYPE(ltype) == POINTER) {
11057
11058         genDataPointerGet (left,result,ic);
11059         pic16_freeAsmop(left, NULL, ic, TRUE);
11060         return ;
11061     }
11062
11063     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11064     pic16_aopOp (result,ic,TRUE);
11065
11066     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11067
11068 #if 1
11069     if(IS_BITFIELD( retype )
11070       && (SPEC_BLEN(operandType(result))==1)
11071     ) {
11072       iCode *nextic;
11073       pCodeOp *jop;
11074       int bitstrt, bytestrt;
11075
11076         /* if this is bitfield of size 1, see if we are checking the value
11077          * of a single bit in an if-statement,
11078          * if yes, then don't generate usual code, but execute the
11079          * genIfx directly -- VR */
11080
11081         nextic = ic->next;
11082
11083         /* CHECK: if next iCode is IFX
11084          * and current result operand is nextic's conditional operand
11085          * and current result operand live ranges ends at nextic's key number
11086          */
11087         if((nextic->op == IFX)
11088           && (result == IC_COND(nextic))
11089           && (OP_LIVETO(result) == nextic->seq)
11090           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11091           ) {
11092             /* everything is ok then */
11093             /* find a way to optimize the genIfx iCode */
11094
11095             bytestrt = SPEC_BSTR(operandType(result))/8;
11096             bitstrt = SPEC_BSTR(operandType(result))%8;
11097
11098             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11099
11100             genIfxpCOpJump(nextic, jop);
11101
11102             pic16_freeAsmop(left, NULL, ic, TRUE);
11103             pic16_freeAsmop(result, NULL, ic, TRUE);
11104             return;
11105         }
11106     }
11107 #endif
11108
11109     /* if bitfield then unpack the bits */
11110     if (IS_BITFIELD(letype))
11111       genUnpackBits (result, left, NULL, POINTER);
11112     else {
11113       /* we have can just get the values */
11114       int size = AOP_SIZE(result);
11115       int offset = 0;
11116
11117       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11118
11119       pic16_loadFSR0( left, 0 );
11120
11121       while(size--) {
11122         if(size) {
11123           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11124                 pic16_popGet(AOP(result), offset++)));
11125         } else {
11126           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11127                 pic16_popGet(AOP(result), offset++)));
11128         }
11129       }
11130     }
11131
11132 #if 0
11133     /* now some housekeeping stuff */
11134     if (aop) {
11135       /* we had to allocate for this iCode */
11136       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11137       pic16_freeAsmop(NULL,aop,ic,TRUE);
11138     } else {
11139       /* we did not allocate which means left
11140        * already in a pointer register, then
11141        * if size > 0 && this could be used again
11142        * we have to point it back to where it
11143        * belongs */
11144       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11145       if (AOP_SIZE(result) > 1
11146         && !OP_SYMBOL(left)->remat
11147         && ( OP_SYMBOL(left)->liveTo > ic->seq
11148             || ic->depth )) {
11149 //        int size = AOP_SIZE(result) - 1;
11150 //        while (size--)
11151 //          pic16_emitcode("dec","%s",rname);
11152         }
11153     }
11154 #endif
11155
11156     /* done */
11157     pic16_freeAsmop(left,NULL,ic,TRUE);
11158     pic16_freeAsmop(result,NULL,ic,TRUE);
11159 }
11160
11161 /*-----------------------------------------------------------------*/
11162 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11163 /*-----------------------------------------------------------------*/
11164 static void genPagedPointerGet (operand *left,
11165                                operand *result,
11166                                iCode *ic)
11167 {
11168     asmop *aop = NULL;
11169     regs *preg = NULL ;
11170     char *rname ;
11171     sym_link *rtype, *retype;
11172
11173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11174
11175     rtype = operandType(result);
11176     retype= getSpec(rtype);
11177
11178     pic16_aopOp(left,ic,FALSE);
11179
11180   /* if the value is already in a pointer register
11181        then don't need anything more */
11182     if (!AOP_INPREG(AOP(left))) {
11183         /* otherwise get a free pointer register */
11184         aop = newAsmop(0);
11185         preg = getFreePtr(ic,&aop,FALSE);
11186         pic16_emitcode("mov","%s,%s",
11187                 preg->name,
11188                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11189         rname = preg->name ;
11190     } else
11191         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11192
11193     pic16_freeAsmop(left,NULL,ic,TRUE);
11194     pic16_aopOp (result,ic,TRUE);
11195
11196     /* if bitfield then unpack the bits */
11197     if (IS_BITFIELD(retype))
11198         genUnpackBits (result,left,rname,PPOINTER);
11199     else {
11200         /* we have can just get the values */
11201         int size = AOP_SIZE(result);
11202         int offset = 0 ;
11203
11204         while (size--) {
11205
11206             pic16_emitcode("movx","a,@%s",rname);
11207             pic16_aopPut(AOP(result),"a",offset);
11208
11209             offset++ ;
11210
11211             if (size)
11212                 pic16_emitcode("inc","%s",rname);
11213         }
11214     }
11215
11216     /* now some housekeeping stuff */
11217     if (aop) {
11218         /* we had to allocate for this iCode */
11219         pic16_freeAsmop(NULL,aop,ic,TRUE);
11220     } else {
11221         /* we did not allocate which means left
11222            already in a pointer register, then
11223            if size > 0 && this could be used again
11224            we have to point it back to where it
11225            belongs */
11226         if (AOP_SIZE(result) > 1 &&
11227             !OP_SYMBOL(left)->remat &&
11228             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11229               ic->depth )) {
11230             int size = AOP_SIZE(result) - 1;
11231             while (size--)
11232                 pic16_emitcode("dec","%s",rname);
11233         }
11234     }
11235
11236     /* done */
11237     pic16_freeAsmop(result,NULL,ic,TRUE);
11238
11239
11240 }
11241
11242 #if 0
11243 /* This code is not adjusted to PIC16 and fails utterly.
11244  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11245
11246 /*-----------------------------------------------------------------*/
11247 /* genFarPointerGet - gget value from far space                    */
11248 /*-----------------------------------------------------------------*/
11249 static void genFarPointerGet (operand *left,
11250                               operand *result, iCode *ic)
11251 {
11252     int size, offset ;
11253     sym_link *retype = getSpec(operandType(result));
11254
11255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11256
11257     pic16_aopOp(left,ic,FALSE);
11258
11259     /* if the operand is already in dptr
11260     then we do nothing else we move the value to dptr */
11261     if (AOP_TYPE(left) != AOP_STR) {
11262         /* if this is remateriazable */
11263         if (AOP_TYPE(left) == AOP_IMMD)
11264             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11265         else { /* we need to get it byte by byte */
11266             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11267             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11268             if (options.model == MODEL_FLAT24)
11269             {
11270                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11271             }
11272         }
11273     }
11274     /* so dptr know contains the address */
11275     pic16_freeAsmop(left,NULL,ic,TRUE);
11276     pic16_aopOp(result,ic,TRUE);
11277
11278     /* if bit then unpack */
11279     if (IS_BITFIELD(retype))
11280         genUnpackBits(result,left,"dptr",FPOINTER);
11281     else {
11282         size = AOP_SIZE(result);
11283         offset = 0 ;
11284
11285         while (size--) {
11286             pic16_emitcode("movx","a,@dptr");
11287             pic16_aopPut(AOP(result),"a",offset++);
11288             if (size)
11289                 pic16_emitcode("inc","dptr");
11290         }
11291     }
11292
11293     pic16_freeAsmop(result,NULL,ic,TRUE);
11294 }
11295 #endif
11296
11297 #if 0
11298 /*-----------------------------------------------------------------*/
11299 /* genCodePointerGet - get value from code space                  */
11300 /*-----------------------------------------------------------------*/
11301 static void genCodePointerGet (operand *left,
11302                                 operand *result, iCode *ic)
11303 {
11304     int size, offset ;
11305     sym_link *retype = getSpec(operandType(result));
11306
11307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11308
11309     pic16_aopOp(left,ic,FALSE);
11310
11311     /* if the operand is already in dptr
11312     then we do nothing else we move the value to dptr */
11313     if (AOP_TYPE(left) != AOP_STR) {
11314         /* if this is remateriazable */
11315         if (AOP_TYPE(left) == AOP_IMMD)
11316             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11317         else { /* we need to get it byte by byte */
11318             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11319             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11320             if (options.model == MODEL_FLAT24)
11321             {
11322                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11323             }
11324         }
11325     }
11326     /* so dptr know contains the address */
11327     pic16_freeAsmop(left,NULL,ic,TRUE);
11328     pic16_aopOp(result,ic,FALSE);
11329
11330     /* if bit then unpack */
11331     if (IS_BITFIELD(retype))
11332         genUnpackBits(result,left,"dptr",CPOINTER);
11333     else {
11334         size = AOP_SIZE(result);
11335         offset = 0 ;
11336
11337         while (size--) {
11338             pic16_emitcode("clr","a");
11339             pic16_emitcode("movc","a,@a+dptr");
11340             pic16_aopPut(AOP(result),"a",offset++);
11341             if (size)
11342                 pic16_emitcode("inc","dptr");
11343         }
11344     }
11345
11346     pic16_freeAsmop(result,NULL,ic,TRUE);
11347 }
11348 #endif
11349
11350 #if 0
11351 /*-----------------------------------------------------------------*/
11352 /* genGenPointerGet - gget value from generic pointer space        */
11353 /*-----------------------------------------------------------------*/
11354 static void genGenPointerGet (operand *left,
11355                               operand *result, iCode *ic)
11356 {
11357   int size, offset, lit;
11358   sym_link *retype = getSpec(operandType(result));
11359
11360         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11361         pic16_aopOp(left,ic,FALSE);
11362         pic16_aopOp(result,ic,FALSE);
11363         size = AOP_SIZE(result);
11364
11365         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11366
11367         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11368
11369                 lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11370                 // load FSR0 from immediate
11371                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11372
11373 //              pic16_loadFSR0( left );
11374
11375                 offset = 0;
11376                 while(size--) {
11377                         if(size) {
11378                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11379                         } else {
11380                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11381                         }
11382                         offset++;
11383                 }
11384                 goto release;
11385
11386         }
11387         else { /* we need to get it byte by byte */
11388                 // set up FSR0 with address from left
11389                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11390                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11391
11392                 offset = 0 ;
11393
11394                 while(size--) {
11395                         if(size) {
11396                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11397                         } else {
11398                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11399                         }
11400                         offset++;
11401                 }
11402                 goto release;
11403         }
11404
11405   /* if bit then unpack */
11406         if (IS_BITFIELD(retype))
11407                 genUnpackBits(result,left,"BAD",GPOINTER);
11408
11409         release:
11410         pic16_freeAsmop(left,NULL,ic,TRUE);
11411         pic16_freeAsmop(result,NULL,ic,TRUE);
11412
11413 }
11414 #endif
11415
11416
11417 /*-----------------------------------------------------------------*/
11418 /* genGenPointerGet - gget value from generic pointer space        */
11419 /*-----------------------------------------------------------------*/
11420 static void genGenPointerGet (operand *left,
11421                               operand *result, iCode *ic)
11422 {
11423   int size, offset, lit;
11424   sym_link *letype = getSpec(operandType(left));
11425
11426     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11427     pic16_aopOp(left,ic,FALSE);
11428     pic16_aopOp(result,ic,TRUE);
11429     size = AOP_SIZE(result);
11430
11431     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11432
11433     /* if bit then unpack */
11434     if (IS_BITFIELD(letype)) {
11435       genUnpackBits(result,left,"BAD",GPOINTER);
11436       goto release;
11437     }
11438
11439     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11440
11441       lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11442       // load FSR0 from immediate
11443       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11444
11445       werror(W_POSSBUG2, __FILE__, __LINE__);
11446
11447       offset = 0;
11448       while(size--) {
11449         if(size) {
11450           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11451         } else {
11452           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11453         }
11454         offset++;
11455       }
11456
11457       goto release;
11458
11459     } else { /* we need to get it byte by byte */
11460
11461       /* set up WREG:PRODL:FSR0L with address from left */
11462       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11463       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11464       pic16_mov2w(AOP(left), 2);
11465       pic16_callGenericPointerRW(0, size);
11466
11467       assignResultValue(result, size, 1);
11468
11469       goto release;
11470     }
11471
11472 release:
11473   pic16_freeAsmop(left,NULL,ic,TRUE);
11474   pic16_freeAsmop(result,NULL,ic,TRUE);
11475 }
11476
11477 /*-----------------------------------------------------------------*/
11478 /* genConstPointerGet - get value from const generic pointer space */
11479 /*-----------------------------------------------------------------*/
11480 static void genConstPointerGet (operand *left,
11481                                 operand *result, iCode *ic)
11482 {
11483   //sym_link *retype = getSpec(operandType(result));
11484   // symbol *albl = newiTempLabel(NULL);        // patch 15
11485   // symbol *blbl = newiTempLabel(NULL);        //
11486   // PIC_OPCODE poc;                            // patch 15
11487   int size;
11488   int offset = 0;
11489
11490   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11491   pic16_aopOp(left,ic,FALSE);
11492   pic16_aopOp(result,ic,TRUE);
11493   size = AOP_SIZE(result);
11494
11495   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11496
11497   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11498
11499   // set up table pointer
11500   if( (AOP_TYPE(left) == AOP_PCODE)
11501       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11502           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11503     {
11504       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11505       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11506       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11507       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11508       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11509       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11510   } else {
11511     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11512     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11513     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11514   }
11515
11516   while(size--) {
11517     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11518     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11519     offset++;
11520   }
11521
11522   pic16_freeAsmop(left,NULL,ic,TRUE);
11523   pic16_freeAsmop(result,NULL,ic,TRUE);
11524 }
11525
11526
11527 /*-----------------------------------------------------------------*/
11528 /* genPointerGet - generate code for pointer get                   */
11529 /*-----------------------------------------------------------------*/
11530 static void genPointerGet (iCode *ic)
11531 {
11532   operand *left, *result ;
11533   sym_link *type, *etype;
11534   int p_type;
11535
11536     FENTRY;
11537
11538     left = IC_LEFT(ic);
11539     result = IC_RESULT(ic) ;
11540
11541     /* depending on the type of pointer we need to
11542     move it to the correct pointer register */
11543     type = operandType(left);
11544     etype = getSpec(type);
11545
11546 #if 0
11547     if (IS_PTR_CONST(type))
11548 #else
11549     if (IS_CODEPTR(type))
11550 #endif
11551       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11552
11553     /* if left is of type of pointer then it is simple */
11554     if (IS_PTR(type) && !IS_FUNC(type->next))
11555       p_type = DCL_TYPE(type);
11556     else {
11557       /* we have to go by the storage class */
11558       p_type = PTR_TYPE(SPEC_OCLS(etype));
11559
11560       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11561
11562       if (SPEC_OCLS(etype)->codesp ) {
11563         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11564         //p_type = CPOINTER ;
11565       } else
11566       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11567         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11568         /*p_type = FPOINTER ;*/
11569       } else
11570       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11571         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11572         /* p_type = PPOINTER; */
11573       } else
11574       if (SPEC_OCLS(etype) == idata ) {
11575         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11576         /* p_type = IPOINTER; */
11577       } else {
11578         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11579         /* p_type = POINTER ; */
11580       }
11581     }
11582
11583     /* now that we have the pointer type we assign
11584     the pointer values */
11585     switch (p_type) {
11586       case POINTER:
11587       case FPOINTER:
11588       case IPOINTER:
11589         genNearPointerGet (left,result,ic);
11590         break;
11591
11592       case PPOINTER:
11593         genPagedPointerGet(left,result,ic);
11594         break;
11595
11596 #if 0
11597       /* PICs do not support FAR pointers... */
11598       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11599       case FPOINTER:
11600         genFarPointerGet (left,result,ic);
11601         break;
11602 #endif
11603
11604       case CPOINTER:
11605         genConstPointerGet (left,result,ic);
11606         //pic16_emitcodePointerGet (left,result,ic);
11607         break;
11608
11609       case GPOINTER:
11610 #if 0
11611       if (IS_PTR_CONST(type))
11612         genConstPointerGet (left,result,ic);
11613       else
11614 #endif
11615         genGenPointerGet (left,result,ic);
11616       break;
11617
11618     default:
11619       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11620               "genPointerGet: illegal pointer type");
11621
11622     }
11623 }
11624
11625 /*-----------------------------------------------------------------*/
11626 /* genPackBits - generates code for packed bit storage             */
11627 /*-----------------------------------------------------------------*/
11628 static void genPackBits (sym_link    *etype , operand *result,
11629                          operand *right ,
11630                          char *rname, int p_type)
11631 {
11632   int shCnt = 0 ;
11633   int offset = 0  ;
11634   int rLen = 0 ;
11635   int blen, bstr ;
11636   int shifted_and_masked = 0;
11637   unsigned long lit = (unsigned long)-1;
11638   sym_link *retype;
11639
11640   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11641   blen = SPEC_BLEN(etype);
11642   bstr = SPEC_BSTR(etype);
11643
11644   retype = getSpec(operandType(right));
11645
11646   if(AOP_TYPE(right) == AOP_LIT) {
11647     lit = ulFromVal (AOP(right)->aopu.aop_lit);
11648
11649     if((blen == 1) && (bstr < 8)) {
11650       /* it is a single bit, so use the appropriate bit instructions */
11651
11652       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11653
11654       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11655         /* workaround to reduce the extra lfsr instruction */
11656         if(lit) {
11657           pic16_emitpcode(POC_BSF,
11658               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11659         } else {
11660           pic16_emitpcode(POC_BCF,
11661               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11662         }
11663       } else {
11664         if (PIC_IS_DATA_PTR(operandType(result))) {
11665           pic16_loadFSR0(result, 0);
11666           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11667               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11668         } else {
11669           /* get old value */
11670           pic16_derefPtr (result, p_type, 0, NULL);
11671           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11672               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11673           /* write back new value */
11674           pic16_derefPtr (result, p_type, 1, NULL);
11675         }
11676       }
11677
11678       return;
11679     }
11680     /* IORLW below is more efficient */
11681     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11682     lit = (lit & ((1UL << blen) - 1)) << bstr;
11683     shifted_and_masked = 1;
11684     offset++;
11685   } else
11686     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11687         && IS_BITFIELD(retype)
11688         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11689         && (blen == 1)) {
11690       int rblen, rbstr;
11691
11692       rblen = SPEC_BLEN( retype );
11693       rbstr = SPEC_BSTR( retype );
11694
11695       if(IS_BITFIELD(etype)) {
11696         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11697         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11698       } else {
11699         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11700       }
11701
11702       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11703
11704       if(IS_BITFIELD(etype)) {
11705         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11706       } else {
11707         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11708       }
11709
11710       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11711
11712       return;
11713     } else {
11714       /* move right to W */
11715       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11716     }
11717
11718   /* if the bit length is less than or   */
11719   /* it exactly fits a byte then         */
11720   if((shCnt=SPEC_BSTR(etype))
11721       || SPEC_BLEN(etype) <= 8 )  {
11722     int fsr0_setup = 0;
11723
11724     if (blen != 8 || (bstr % 8) != 0) {
11725       // we need to combine the value with the old value
11726       if(!shifted_and_masked)
11727       {
11728         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11729
11730         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11731             SPEC_BSTR(etype), SPEC_BLEN(etype));
11732
11733         /* shift left acc, do NOT mask the result again */
11734         AccLsh(shCnt, 0);
11735
11736         /* using PRODH as a temporary register here */
11737         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11738       }
11739
11740       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11741         || IS_DIRECT(result)) {
11742         /* access symbol directly */
11743         pic16_mov2w (AOP(result), 0);
11744       } else {
11745         /* get old value */
11746         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11747       }
11748 #if 1
11749       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11750             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11751                             (unsigned char)(0xff >> (8-bstr))) ));
11752       if (!shifted_and_masked) {
11753         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11754       } else {
11755         /* We have the shifted and masked (literal) right value in `lit' */
11756         if (lit != 0)
11757           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11758       }
11759     } else { // if (blen == 8 && (bstr % 8) == 0)
11760         if (shifted_and_masked) {
11761             // move right (literal) to WREG (only case where right is not yet in WREG)
11762             pic16_mov2w(AOP(right), (bstr / 8));
11763         }
11764     }
11765
11766     /* write new value back */
11767     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11768         || IS_DIRECT(result)) {
11769       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11770     } else {
11771       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11772     }
11773 #endif
11774
11775     return;
11776   }
11777
11778
11779 #if 0
11780   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11781   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11782   exit(EXIT_FAILURE);
11783 #endif
11784
11785
11786   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11787   rLen = SPEC_BLEN(etype)-8;
11788
11789   /* now generate for lengths greater than one byte */
11790   while (1) {
11791     rLen -= 8 ;
11792     if (rLen <= 0 ) {
11793       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11794       break ;
11795     }
11796
11797     switch (p_type) {
11798       case POINTER:
11799         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11800         break;
11801
11802         /*
11803            case FPOINTER:
11804            MOVA(l);
11805            pic16_emitcode("movx","@dptr,a");
11806            break;
11807
11808            case GPOINTER:
11809            MOVA(l);
11810            DEBUGpic16_emitcode(";lcall","__gptrput");
11811            break;
11812          */
11813       default:
11814         assert(0);
11815     }
11816
11817
11818     pic16_mov2w(AOP(right), offset++);
11819   }
11820
11821   /* last last was not complete */
11822   if (rLen)   {
11823     /* save the byte & read byte */
11824     switch (p_type) {
11825       case POINTER:
11826         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11827         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11828         break;
11829
11830         /*
11831            case FPOINTER:
11832            pic16_emitcode ("mov","b,a");
11833            pic16_emitcode("movx","a,@dptr");
11834            break;
11835
11836            case GPOINTER:
11837            pic16_emitcode ("push","b");
11838            pic16_emitcode ("push","acc");
11839            pic16_emitcode ("lcall","__gptrget");
11840            pic16_emitcode ("pop","b");
11841            break;
11842          */
11843       default:
11844         assert(0);
11845     }
11846     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11847     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11848     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11849     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11850     //        pic16_emitcode ("orl","a,b");
11851   }
11852
11853   //    if (p_type == GPOINTER)
11854   //        pic16_emitcode("pop","b");
11855
11856   switch (p_type) {
11857
11858     case POINTER:
11859       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11860       //        pic16_emitcode("mov","@%s,a",rname);
11861       break;
11862       /*
11863          case FPOINTER:
11864          pic16_emitcode("movx","@dptr,a");
11865          break;
11866
11867          case GPOINTER:
11868          DEBUGpic16_emitcode(";lcall","__gptrput");
11869          break;
11870        */
11871     default:
11872       assert(0);
11873   }
11874
11875   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11876 }
11877
11878 /*-----------------------------------------------------------------*/
11879 /* genDataPointerSet - remat pointer to data space                 */
11880 /*-----------------------------------------------------------------*/
11881 static void genDataPointerSet(operand *right,
11882                               operand *result,
11883                               iCode *ic)
11884 {
11885   int size, offset = 0, resoffset=0 ;
11886
11887     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11888     pic16_aopOp(right,ic,FALSE);
11889
11890     size = AOP_SIZE(right);
11891
11892 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11893
11894 #if 0
11895     if ( AOP_TYPE(result) == AOP_PCODE) {
11896       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11897               AOP(result)->aopu.pcop->name,
11898                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11899               PCOR(AOP(result)->aopu.pcop)->instance:
11900               PCOI(AOP(result)->aopu.pcop)->offset);
11901     }
11902 #endif
11903
11904     if(AOP(result)->aopu.pcop->type == PO_DIR)
11905       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11906
11907     while (size--) {
11908       if (AOP_TYPE(right) == AOP_LIT) {
11909         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11910         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11911       } else {
11912         pic16_mov2w(AOP(right), offset);
11913         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11914       }
11915       offset++;
11916       resoffset++;
11917     }
11918
11919     pic16_freeAsmop(right,NULL,ic,TRUE);
11920 }
11921
11922
11923
11924 /*-----------------------------------------------------------------*/
11925 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11926 /*-----------------------------------------------------------------*/
11927 static void genNearPointerSet (operand *right,
11928                                operand *result,
11929                                iCode *ic)
11930 {
11931   asmop *aop = NULL;
11932   sym_link *retype;
11933   sym_link *ptype = operandType(result);
11934   sym_link *resetype;
11935
11936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11937     retype= getSpec(operandType(right));
11938     resetype = getSpec(operandType(result));
11939
11940     pic16_aopOp(result,ic,FALSE);
11941
11942     /* if the result is rematerializable &
11943      * in data space & not a bit variable */
11944
11945     /* and result is not a bit variable */
11946     if (AOP_TYPE(result) == AOP_PCODE
11947 //      && AOP_TYPE(result) == AOP_IMMD
11948       && DCL_TYPE(ptype) == POINTER
11949       && !IS_BITFIELD(retype)
11950       && !IS_BITFIELD(resetype)) {
11951
11952         genDataPointerSet (right,result,ic);
11953         pic16_freeAsmop(result,NULL,ic,TRUE);
11954       return;
11955     }
11956
11957     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11958     pic16_aopOp(right,ic,FALSE);
11959     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11960
11961     /* if bitfield then unpack the bits */
11962     if (IS_BITFIELD(resetype)) {
11963       genPackBits (resetype, result, right, NULL, POINTER);
11964     } else {
11965       /* we have can just get the values */
11966       int size = AOP_SIZE(right);
11967       int offset = 0 ;
11968
11969         pic16_loadFSR0(result, 0);
11970
11971         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11972         while (size--) {
11973           if (is_LitOp(right)) {
11974             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11975             if (size) {
11976               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11977             } else {
11978               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11979             }
11980           } else { // no literal
11981             if(size) {
11982               pic16_emitpcode(POC_MOVFF,
11983                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11984                   pic16_popCopyReg(&pic16_pc_postinc0)));
11985             } else {
11986               pic16_emitpcode(POC_MOVFF,
11987                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11988                   pic16_popCopyReg(&pic16_pc_indf0)));
11989             }
11990           }
11991
11992           offset++;
11993         }
11994     }
11995
11996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11997     /* now some housekeeping stuff */
11998     if (aop) {
11999       /* we had to allocate for this iCode */
12000       pic16_freeAsmop(NULL,aop,ic,TRUE);
12001     } else {
12002       /* we did not allocate which means left
12003        * already in a pointer register, then
12004        * if size > 0 && this could be used again
12005        * we have to point it back to where it
12006        * belongs */
12007       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12008       if (AOP_SIZE(right) > 1
12009         && !OP_SYMBOL(result)->remat
12010         && ( OP_SYMBOL(result)->liveTo > ic->seq
12011         || ic->depth )) {
12012
12013           int size = AOP_SIZE(right) - 1;
12014
12015             while (size--)
12016               pic16_emitcode("decf","fsr0,f");
12017               //pic16_emitcode("dec","%s",rname);
12018       }
12019     }
12020
12021     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12022     /* done */
12023 //release:
12024     pic16_freeAsmop(right,NULL,ic,TRUE);
12025     pic16_freeAsmop(result,NULL,ic,TRUE);
12026 }
12027
12028 /*-----------------------------------------------------------------*/
12029 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12030 /*-----------------------------------------------------------------*/
12031 static void genPagedPointerSet (operand *right,
12032                                operand *result,
12033                                iCode *ic)
12034 {
12035     asmop *aop = NULL;
12036     regs *preg = NULL ;
12037     char *rname , *l;
12038     sym_link *retype;
12039
12040     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12041
12042     retype= getSpec(operandType(right));
12043
12044     pic16_aopOp(result,ic,FALSE);
12045
12046     /* if the value is already in a pointer register
12047        then don't need anything more */
12048     if (!AOP_INPREG(AOP(result))) {
12049         /* otherwise get a free pointer register */
12050         aop = newAsmop(0);
12051         preg = getFreePtr(ic,&aop,FALSE);
12052         pic16_emitcode("mov","%s,%s",
12053                 preg->name,
12054                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12055         rname = preg->name ;
12056     } else
12057         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12058
12059     pic16_freeAsmop(result,NULL,ic,TRUE);
12060     pic16_aopOp (right,ic,FALSE);
12061
12062     /* if bitfield then unpack the bits */
12063     if (IS_BITFIELD(retype))
12064         genPackBits (retype,result,right,rname,PPOINTER);
12065     else {
12066         /* we have can just get the values */
12067         int size = AOP_SIZE(right);
12068         int offset = 0 ;
12069
12070         while (size--) {
12071             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12072
12073             MOVA(l);
12074             pic16_emitcode("movx","@%s,a",rname);
12075
12076             if (size)
12077                 pic16_emitcode("inc","%s",rname);
12078
12079             offset++;
12080         }
12081     }
12082
12083     /* now some housekeeping stuff */
12084     if (aop) {
12085         /* we had to allocate for this iCode */
12086         pic16_freeAsmop(NULL,aop,ic,TRUE);
12087     } else {
12088         /* we did not allocate which means left
12089            already in a pointer register, then
12090            if size > 0 && this could be used again
12091            we have to point it back to where it
12092            belongs */
12093         if (AOP_SIZE(right) > 1 &&
12094             !OP_SYMBOL(result)->remat &&
12095             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12096               ic->depth )) {
12097             int size = AOP_SIZE(right) - 1;
12098             while (size--)
12099                 pic16_emitcode("dec","%s",rname);
12100         }
12101     }
12102
12103     /* done */
12104     pic16_freeAsmop(right,NULL,ic,TRUE);
12105
12106
12107 }
12108
12109 #if 0
12110 /* This code is not adjusted to PIC16 and fails utterly...
12111  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12112
12113 /*-----------------------------------------------------------------*/
12114 /* genFarPointerSet - set value from far space                     */
12115 /*-----------------------------------------------------------------*/
12116 static void genFarPointerSet (operand *right,
12117                               operand *result, iCode *ic)
12118 {
12119     int size, offset ;
12120     sym_link *retype = getSpec(operandType(right));
12121
12122     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12123     pic16_aopOp(result,ic,FALSE);
12124
12125     /* if the operand is already in dptr
12126     then we do nothing else we move the value to dptr */
12127     if (AOP_TYPE(result) != AOP_STR) {
12128         /* if this is remateriazable */
12129         if (AOP_TYPE(result) == AOP_IMMD)
12130             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12131         else { /* we need to get it byte by byte */
12132             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12133             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12134             if (options.model == MODEL_FLAT24)
12135             {
12136                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12137             }
12138         }
12139     }
12140     /* so dptr know contains the address */
12141     pic16_freeAsmop(result,NULL,ic,TRUE);
12142     pic16_aopOp(right,ic,FALSE);
12143
12144     /* if bit then unpack */
12145     if (IS_BITFIELD(retype))
12146         genPackBits(retype,result,right,"dptr",FPOINTER);
12147     else {
12148         size = AOP_SIZE(right);
12149         offset = 0 ;
12150
12151         while (size--) {
12152             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12153             MOVA(l);
12154             pic16_emitcode("movx","@dptr,a");
12155             if (size)
12156                 pic16_emitcode("inc","dptr");
12157         }
12158     }
12159
12160     pic16_freeAsmop(right,NULL,ic,TRUE);
12161 }
12162 #endif
12163
12164 /*-----------------------------------------------------------------*/
12165 /* genGenPointerSet - set value from generic pointer space         */
12166 /*-----------------------------------------------------------------*/
12167 #if 0
12168 static void genGenPointerSet (operand *right,
12169                               operand *result, iCode *ic)
12170 {
12171         int i, size, offset, lit;
12172         sym_link *retype = getSpec(operandType(right));
12173
12174         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12175
12176         pic16_aopOp(result,ic,FALSE);
12177         pic16_aopOp(right,ic,FALSE);
12178         size = AOP_SIZE(right);
12179         offset = 0;
12180
12181         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12182
12183         /* if the operand is already in dptr
12184                 then we do nothing else we move the value to dptr */
12185         if (AOP_TYPE(result) != AOP_STR) {
12186                 /* if this is remateriazable */
12187                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12188                 // WARNING: anythig until "else" is untested!
12189                 if (AOP_TYPE(result) == AOP_IMMD) {
12190                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12191                         lit = (unsigned) ulFromVal (AOP(result)->aopu.aop_lit);
12192                         // load FSR0 from immediate
12193                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12194                         offset = 0;
12195                         while(size--) {
12196                                 if(size) {
12197                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12198                                 } else {
12199                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12200                                 }
12201                                 offset++;
12202                         }
12203                         goto release;
12204                 }
12205                 else { /* we need to get it byte by byte */
12206                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12207                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12208
12209                         // set up FSR0 with address of result
12210                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12211                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12212
12213                         /* hack hack! see if this the FSR. If so don't load W */
12214                         if(AOP_TYPE(right) != AOP_ACC) {
12215
12216                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12217
12218                                 if(AOP_TYPE(right) == AOP_LIT)
12219                                 {
12220                                         // copy literal
12221                                         // note: pic16_popGet handles sign extension
12222                                         for(i=0;i<size;i++) {
12223                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12224                                                 if(i < size-1)
12225                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12226                                                 else
12227                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12228                                         }
12229                                 } else {
12230                                         // copy regs
12231
12232                                         for(i=0;i<size;i++) {
12233                                                 if(i < size-1)
12234                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12235                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12236                                                 else
12237                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12238                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12239                                         }
12240                                 }
12241                                 goto release;
12242                         }
12243                         // right = ACC
12244                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12245                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12246                         goto release;
12247         } // if (AOP_TYPE(result) != AOP_IMMD)
12248
12249         } // if (AOP_TYPE(result) != AOP_STR)
12250         /* so dptr know contains the address */
12251
12252
12253         /* if bit then unpack */
12254         if (IS_BITFIELD(retype))
12255                 genPackBits(retype,result,right,"dptr",GPOINTER);
12256         else {
12257                 size = AOP_SIZE(right);
12258                 offset = 0 ;
12259
12260                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12261
12262                 // set up FSR0 with address of result
12263                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12264                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12265
12266                 while (size--) {
12267                         if (AOP_TYPE(right) == AOP_LIT) {
12268                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12269                                 if (size) {
12270                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12271                                 } else {
12272                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12273                                 }
12274                         } else { // no literal
12275                                 if(size) {
12276                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12277                                 } else {
12278                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12279                                 }
12280                         }
12281                         offset++;
12282                 }
12283         }
12284
12285         release:
12286         pic16_freeAsmop(right,NULL,ic,TRUE);
12287         pic16_freeAsmop(result,NULL,ic,TRUE);
12288 }
12289 #endif
12290
12291 static void genGenPointerSet (operand *right,
12292                               operand *result, iCode *ic)
12293 {
12294   int size;
12295   sym_link *retype = getSpec(operandType(result));
12296
12297     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12298
12299     pic16_aopOp(result,ic,FALSE);
12300     pic16_aopOp(right,ic,FALSE);
12301     size = AOP_SIZE(right);
12302
12303     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12304
12305
12306     /* if bit then unpack */
12307     if (IS_BITFIELD(retype)) {
12308 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12309       genPackBits(retype,result,right,"dptr",GPOINTER);
12310       goto release;
12311     }
12312
12313     size = AOP_SIZE(right);
12314
12315     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12316
12317
12318     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12319
12320     /* value of right+0 is placed on stack, which will be retrieved
12321      * by the support function thus restoring the stack. The important
12322      * thing is that there is no need to manually restore stack pointer
12323      * here */
12324     pushaop(AOP(right), 0);
12325 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12326     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12327     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12328     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12329
12330     /* load address to write to in WREG:FSR0H:FSR0L */
12331     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12332                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12333     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12334                                 pic16_popCopyReg(&pic16_pc_prodl)));
12335     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12336
12337     pic16_callGenericPointerRW(1, size);
12338
12339 release:
12340     pic16_freeAsmop(right,NULL,ic,TRUE);
12341     pic16_freeAsmop(result,NULL,ic,TRUE);
12342 }
12343
12344 /*-----------------------------------------------------------------*/
12345 /* genPointerSet - stores the value into a pointer location        */
12346 /*-----------------------------------------------------------------*/
12347 static void genPointerSet (iCode *ic)
12348 {
12349   operand *right, *result ;
12350   sym_link *type, *etype;
12351   int p_type;
12352
12353     FENTRY;
12354
12355     right = IC_RIGHT(ic);
12356     result = IC_RESULT(ic) ;
12357
12358     /* depending on the type of pointer we need to
12359     move it to the correct pointer register */
12360     type = operandType(result);
12361     etype = getSpec(type);
12362
12363     /* if left is of type of pointer then it is simple */
12364     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12365         p_type = DCL_TYPE(type);
12366     }
12367     else {
12368         /* we have to go by the storage class */
12369         p_type = PTR_TYPE(SPEC_OCLS(etype));
12370
12371 /*      if (SPEC_OCLS(etype)->codesp ) { */
12372 /*          p_type = CPOINTER ;  */
12373 /*      } */
12374 /*      else */
12375 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12376 /*              p_type = FPOINTER ; */
12377 /*          else */
12378 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12379 /*                  p_type = PPOINTER ; */
12380 /*              else */
12381 /*                  if (SPEC_OCLS(etype) == idata ) */
12382 /*                      p_type = IPOINTER ; */
12383 /*                  else */
12384 /*                      p_type = POINTER ; */
12385     }
12386
12387     /* now that we have the pointer type we assign
12388     the pointer values */
12389     switch (p_type) {
12390       case POINTER:
12391       case FPOINTER:
12392       case IPOINTER:
12393         genNearPointerSet (right,result,ic);
12394         break;
12395
12396       case PPOINTER:
12397         genPagedPointerSet (right,result,ic);
12398         break;
12399
12400 #if 0
12401       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12402       case FPOINTER:
12403         genFarPointerSet (right,result,ic);
12404         break;
12405 #endif
12406
12407       case GPOINTER:
12408         genGenPointerSet (right,result,ic);
12409         break;
12410
12411       default:
12412         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12413           "genPointerSet: illegal pointer type");
12414     }
12415 }
12416
12417 /*-----------------------------------------------------------------*/
12418 /* genIfx - generate code for Ifx statement                        */
12419 /*-----------------------------------------------------------------*/
12420 static void genIfx (iCode *ic, iCode *popIc)
12421 {
12422   operand *cond = IC_COND(ic);
12423   int isbit =0;
12424
12425     FENTRY;
12426
12427     pic16_aopOp(cond,ic,FALSE);
12428
12429     /* get the value into acc */
12430     if (AOP_TYPE(cond) != AOP_CRY)
12431       pic16_toBoolean(cond);
12432     else
12433       isbit = 1;
12434     /* the result is now in the accumulator */
12435     pic16_freeAsmop(cond,NULL,ic,TRUE);
12436
12437     /* if there was something to be popped then do it */
12438     if (popIc)
12439       genIpop(popIc);
12440
12441     /* if the condition is  a bit variable */
12442     if (isbit && IS_ITEMP(cond) &&
12443         SPIL_LOC(cond)) {
12444       genIfxJump(ic,"c");
12445       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12446     } else {
12447       if (isbit && !IS_ITEMP(cond))
12448         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12449         else
12450         genIfxJump(ic,"a");
12451     }
12452     ic->generated = 1;
12453 }
12454
12455 /*-----------------------------------------------------------------*/
12456 /* genAddrOf - generates code for address of                       */
12457 /*-----------------------------------------------------------------*/
12458 static void genAddrOf (iCode *ic)
12459 {
12460   operand *result, *left;
12461   int size;
12462   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12463   pCodeOp *pcop0, *pcop1, *pcop2;
12464
12465     FENTRY;
12466
12467     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12468
12469     sym = OP_SYMBOL( IC_LEFT(ic) );
12470
12471     if(sym->onStack) {
12472       /* get address of symbol on stack */
12473       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12474 #if 0
12475       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12476                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12477 #endif
12478
12479       // operands on stack are accessible via "FSR2 + index" with index
12480       // starting at 2 for arguments and growing from 0 downwards for
12481       // local variables (index == 0 is not assigned so we add one here)
12482       {
12483         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12484
12485           if (soffs <= 0) {
12486             assert (soffs < 0);
12487             soffs++;
12488           } // if
12489
12490           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12491           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12492           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12493           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12494           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12495           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12496           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12497       }
12498
12499       goto release;
12500     }
12501
12502 //      if(pic16_debug_verbose) {
12503 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12504 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12505 //      }
12506
12507     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12508     size = AOP_SIZE(IC_RESULT(ic));
12509
12510     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12511     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12513
12514     if (size == 3) {
12515       pic16_emitpcode(POC_MOVLW, pcop0);
12516       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12517       pic16_emitpcode(POC_MOVLW, pcop1);
12518       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12519       pic16_emitpcode(POC_MOVLW, pcop2);
12520       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12521     } else
12522     if (size == 2) {
12523       pic16_emitpcode(POC_MOVLW, pcop0);
12524       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12525       pic16_emitpcode(POC_MOVLW, pcop1);
12526     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12527     } else {
12528       pic16_emitpcode(POC_MOVLW, pcop0);
12529       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12530     }
12531
12532     pic16_freeAsmop(left, NULL, ic, FALSE);
12533 release:
12534     pic16_freeAsmop(result,NULL,ic,TRUE);
12535 }
12536
12537
12538 #if 0
12539 /*-----------------------------------------------------------------*/
12540 /* genFarFarAssign - assignment when both are in far space         */
12541 /*-----------------------------------------------------------------*/
12542 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12543 {
12544     int size = AOP_SIZE(right);
12545     int offset = 0;
12546     char *l ;
12547     /* first push the right side on to the stack */
12548     while (size--) {
12549         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12550         MOVA(l);
12551         pic16_emitcode ("push","acc");
12552     }
12553
12554     pic16_freeAsmop(right,NULL,ic,FALSE);
12555     /* now assign DPTR to result */
12556     pic16_aopOp(result,ic,FALSE);
12557     size = AOP_SIZE(result);
12558     while (size--) {
12559         pic16_emitcode ("pop","acc");
12560         pic16_aopPut(AOP(result),"a",--offset);
12561     }
12562     pic16_freeAsmop(result,NULL,ic,FALSE);
12563
12564 }
12565 #endif
12566
12567 /*-----------------------------------------------------------------*/
12568 /* genAssign - generate code for assignment                        */
12569 /*-----------------------------------------------------------------*/
12570 static void genAssign (iCode *ic)
12571 {
12572   operand *result, *right;
12573   sym_link *restype, *rtype;
12574   int size, offset,know_W;
12575   unsigned long lit = 0L;
12576
12577     result = IC_RESULT(ic);
12578     right  = IC_RIGHT(ic) ;
12579
12580     FENTRY;
12581
12582     /* if they are the same */
12583     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12584       return ;
12585
12586     /* reversed order operands are aopOp'ed so that result operand
12587      * is effective in case right is a stack symbol. This maneauver
12588      * allows to use the _G.resDirect flag later */
12589      pic16_aopOp(result,ic,TRUE);
12590     pic16_aopOp(right,ic,FALSE);
12591
12592     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12593
12594     /* if they are the same registers */
12595     if (pic16_sameRegs(AOP(right),AOP(result)))
12596       goto release;
12597
12598     /* if the result is a bit */
12599     if (AOP_TYPE(result) == AOP_CRY) {
12600       /* if the right size is a literal then
12601          we know what the value is */
12602       if (AOP_TYPE(right) == AOP_LIT) {
12603
12604         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12605             pic16_popGet(AOP(result),0));
12606
12607         if (((int) operandLitValue(right)))
12608           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12609               AOP(result)->aopu.aop_dir,
12610               AOP(result)->aopu.aop_dir);
12611         else
12612           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12613               AOP(result)->aopu.aop_dir,
12614               AOP(result)->aopu.aop_dir);
12615
12616         goto release;
12617       }
12618
12619       /* the right is also a bit variable */
12620       if (AOP_TYPE(right) == AOP_CRY) {
12621         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12622         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12623         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12624
12625         goto release ;
12626       }
12627
12628       /* we need to or */
12629       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12630       pic16_toBoolean(right);
12631       emitSKPZ;
12632       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12633       //pic16_aopPut(AOP(result),"a",0);
12634       goto release ;
12635     }
12636
12637     /* bit variables done */
12638     /* general case */
12639     size = AOP_SIZE(result);
12640     offset = 0 ;
12641
12642   /* bit variables done */
12643   /* general case */
12644   size = AOP_SIZE(result);
12645   restype = operandType(result);
12646   rtype = operandType(right);
12647   offset = 0 ;
12648
12649   if(AOP_TYPE(right) == AOP_LIT) {
12650     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12651     {
12652       lit = ulFromVal (AOP(right)->aopu.aop_lit);
12653
12654       /* patch tag for literals that are cast to pointers */
12655       if (IS_CODEPTR(restype)) {
12656         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12657         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12658       } else {
12659         if (IS_GENPTR(restype))
12660         {
12661           if (IS_CODEPTR(rtype)) {
12662             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12663             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12664           } else if (PIC_IS_DATA_PTR(rtype)) {
12665             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12666             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12667           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12668             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12669           } else if (IS_PTR(rtype)) {
12670             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12671             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12672           }
12673         }
12674       }
12675     } else {
12676       union {
12677         unsigned long lit_int;
12678         float lit_float;
12679       } info;
12680
12681
12682       if(IS_FIXED16X16(operandType(right))) {
12683         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12684       } else {
12685         /* take care if literal is a float */
12686         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12687         lit = info.lit_int;
12688       }
12689     }
12690   }
12691
12692 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12693 //                      sizeof(unsigned long int), sizeof(float));
12694
12695
12696     if (AOP_TYPE(right) == AOP_REG) {
12697       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12698       while (size--) {
12699         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12700       } // while
12701       goto release;
12702     }
12703
12704     /* when do we have to read the program memory?
12705      * - if right itself is a symbol in code space
12706      *   (we don't care what it points to if it's a pointer)
12707      * - AND right is not a function (we would want its address)
12708      */
12709     if(AOP_TYPE(right) != AOP_LIT
12710       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12711       && !IS_FUNC(OP_SYM_TYPE(right))
12712       && !IS_ITEMP(right)) {
12713
12714       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12715       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12716
12717       // set up table pointer
12718       if(is_LitOp(right)) {
12719 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12720         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12721         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12722         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12723         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12724         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12725         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12726       } else {
12727 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12728         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12729             pic16_popCopyReg(&pic16_pc_tblptrl)));
12730         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12731             pic16_popCopyReg(&pic16_pc_tblptrh)));
12732         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12733             pic16_popCopyReg(&pic16_pc_tblptru)));
12734       }
12735
12736       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12737       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12738       while(size--) {
12739         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12740         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12741             pic16_popGet(AOP(result),offset)));
12742         offset++;
12743       }
12744
12745       /* FIXME: for pointers we need to extend differently (according
12746        * to pointer type DATA/CODE/EEPROM/... :*/
12747       size = getSize(OP_SYM_TYPE(right));
12748       if(AOP_SIZE(result) > size) {
12749         size = AOP_SIZE(result) - size;
12750         while(size--) {
12751           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12752           offset++;
12753         }
12754       }
12755       goto release;
12756     }
12757
12758 #if 0
12759     /* VR - What is this?! */
12760     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12761       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12762
12763       if(aopIdx(AOP(result),0) == 4) {
12764         /* this is a workaround to save value of right into wreg too,
12765          * value of wreg is going to be used later */
12766         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12767         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12768         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12769         goto release;
12770       } else
12771 //      assert(0);
12772       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12773     }
12774 #endif
12775
12776     size = AOP_SIZE(right);
12777     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12778     know_W=-1;
12779     while (size--) {
12780       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12781       if(AOP_TYPE(right) == AOP_LIT) {
12782         if(lit&0xff) {
12783           if(know_W != (lit&0xff))
12784             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12785           know_W = lit&0xff;
12786           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12787         } else
12788           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12789
12790         lit >>= 8;
12791
12792       } else if (AOP_TYPE(right) == AOP_CRY) {
12793         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12794         if(offset == 0) {
12795           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12796           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12797           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12798         }
12799       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12800         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12801         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12802       } else {
12803         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12804
12805         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12806           if(AOP_TYPE(result) == AOP_ACC) {
12807             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12808           } else
12809             if(AOP_TYPE(right) == AOP_ACC) {
12810               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12811             } else {
12812               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12813             }
12814         }
12815       }
12816
12817       offset++;
12818     }
12819     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12820
12821 release:
12822   pic16_freeAsmop (right,NULL,ic,FALSE);
12823   pic16_freeAsmop (result,NULL,ic,TRUE);
12824 }
12825
12826 /*-----------------------------------------------------------------*/
12827 /* genJumpTab - generates code for jump table                       */
12828 /*-----------------------------------------------------------------*/
12829 static void genJumpTab (iCode *ic)
12830 {
12831   symbol *jtab;
12832   char *l;
12833   pCodeOp *jt_offs;
12834   pCodeOp *jt_offs_hi;
12835   pCodeOp *jt_label;
12836
12837     FENTRY;
12838
12839     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12840     /* get the condition into accumulator */
12841     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12842     MOVA(l);
12843     /* multiply by three */
12844     pic16_emitcode("add","a,acc");
12845     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12846
12847     jtab = newiTempLabel(NULL);
12848     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12849     pic16_emitcode("jmp","@a+dptr");
12850     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12851
12852 #if 0
12853     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12854     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12855     emitSKPNC;
12856     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12857     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12858     pic16_emitpLabel(jtab->key);
12859
12860 #else
12861
12862     jt_offs = pic16_popGetTempReg(0);
12863     jt_offs_hi = pic16_popGetTempReg(1);
12864     jt_label = pic16_popGetLabel (jtab->key);
12865     //fprintf (stderr, "Creating jump table...\n");
12866
12867     // calculate offset into jump table (idx * sizeof (GOTO))
12868     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12869     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12870     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12871     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12872     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12873     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12874     pic16_emitpcode(POC_MOVWF , jt_offs);
12875
12876     // prepare PCLATx (set to first entry in jump table)
12877     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12878     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12879     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12880     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12881     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12882
12883     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12884     pic16_emitpcode(POC_ADDWF , jt_offs);
12885     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12886     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12887     emitSKPNC;
12888     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12889
12890     // release temporaries and prepare jump into table (new PCL --> WREG)
12891     pic16_emitpcode(POC_MOVFW , jt_offs);
12892     pic16_popReleaseTempReg (jt_offs_hi, 1);
12893     pic16_popReleaseTempReg (jt_offs, 0);
12894
12895     // jump into the table
12896     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12897
12898     pic16_emitpLabelFORCE(jtab->key);
12899 #endif
12900
12901     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12902 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12903
12904     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12905     /* now generate the jump labels */
12906     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12907          jtab = setNextItem(IC_JTLABELS(ic))) {
12908 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12909         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12910
12911     }
12912     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12913
12914 }
12915
12916 /*-----------------------------------------------------------------*/
12917 /* genMixedOperation - gen code for operators between mixed types  */
12918 /*-----------------------------------------------------------------*/
12919 /*
12920   TSD - Written for the PIC port - but this unfortunately is buggy.
12921   This routine is good in that it is able to efficiently promote
12922   types to different (larger) sizes. Unfortunately, the temporary
12923   variables that are optimized out by this routine are sometimes
12924   used in other places. So until I know how to really parse the
12925   iCode tree, I'm going to not be using this routine :(.
12926 */
12927 static int genMixedOperation (iCode *ic)
12928 {
12929 #if 0
12930   operand *result = IC_RESULT(ic);
12931   sym_link *ctype = operandType(IC_LEFT(ic));
12932   operand *right = IC_RIGHT(ic);
12933   int ret = 0;
12934   int big,small;
12935   int offset;
12936
12937   iCode *nextic;
12938   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12939
12940   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12941
12942   nextic = ic->next;
12943   if(!nextic)
12944     return 0;
12945
12946   nextright = IC_RIGHT(nextic);
12947   nextleft  = IC_LEFT(nextic);
12948   nextresult = IC_RESULT(nextic);
12949
12950   pic16_aopOp(right,ic,FALSE);
12951   pic16_aopOp(result,ic,FALSE);
12952   pic16_aopOp(nextright,  nextic, FALSE);
12953   pic16_aopOp(nextleft,   nextic, FALSE);
12954   pic16_aopOp(nextresult, nextic, FALSE);
12955
12956   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12957
12958     operand *t = right;
12959     right = nextright;
12960     nextright = t;
12961
12962     pic16_emitcode(";remove right +","");
12963
12964   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12965 /*
12966     operand *t = right;
12967     right = nextleft;
12968     nextleft = t;
12969 */
12970     pic16_emitcode(";remove left +","");
12971   } else
12972     return 0;
12973
12974   big = AOP_SIZE(nextleft);
12975   small = AOP_SIZE(nextright);
12976
12977   switch(nextic->op) {
12978
12979   case '+':
12980     pic16_emitcode(";optimize a +","");
12981     /* if unsigned or not an integral type */
12982     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12983       pic16_emitcode(";add a bit to something","");
12984     } else {
12985
12986       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12987
12988       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12989         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12990         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12991       } else
12992         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12993
12994       offset = 0;
12995       while(--big) {
12996
12997         offset++;
12998
12999         if(--small) {
13000           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13001             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13002             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13003           }
13004
13005           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13006           emitSKPNC;
13007           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13008                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13009                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13010           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13011           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13012
13013         } else {
13014           pic16_emitcode("rlf","known_zero,w");
13015
13016           /*
13017             if right is signed
13018               btfsc  right,7
13019                addlw ff
13020           */
13021           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13022             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13023             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13024           } else {
13025             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13026           }
13027         }
13028       }
13029       ret = 1;
13030     }
13031   }
13032   ret = 1;
13033
13034 release:
13035   pic16_freeAsmop(right,NULL,ic,TRUE);
13036   pic16_freeAsmop(result,NULL,ic,TRUE);
13037   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13038   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13039   if(ret)
13040     nextic->generated = 1;
13041
13042   return ret;
13043 #else
13044   return 0;
13045 #endif
13046 }
13047 /*-----------------------------------------------------------------*/
13048 /* genCast - gen code for casting                                  */
13049 /*-----------------------------------------------------------------*/
13050 static void genCast (iCode *ic)
13051 {
13052   operand *result = IC_RESULT(ic);
13053   sym_link *ctype = operandType(IC_LEFT(ic));
13054   sym_link *rtype = operandType(IC_RIGHT(ic));
13055   sym_link *restype = operandType(IC_RESULT(ic));
13056   operand *right = IC_RIGHT(ic);
13057   int size, offset ;
13058
13059
13060     FENTRY;
13061
13062         /* if they are equivalent then do nothing */
13063 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13064 //              return ;
13065
13066         pic16_aopOp(result,ic,FALSE);
13067         pic16_aopOp(right,ic,FALSE) ;
13068
13069         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13070
13071
13072         /* if the result is a bit */
13073         if (AOP_TYPE(result) == AOP_CRY) {
13074
13075                 /* if the right size is a literal then
13076                  * we know what the value is */
13077                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13078
13079                 if (AOP_TYPE(right) == AOP_LIT) {
13080                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13081                                 pic16_popGet(AOP(result),0));
13082
13083                         if (((int) operandLitValue(right)))
13084                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13085                                         AOP(result)->aopu.aop_dir,
13086                                         AOP(result)->aopu.aop_dir);
13087                         else
13088                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13089                                         AOP(result)->aopu.aop_dir,
13090                                         AOP(result)->aopu.aop_dir);
13091                         goto release;
13092                 }
13093
13094                 /* the right is also a bit variable */
13095                 if (AOP_TYPE(right) == AOP_CRY) {
13096                         emitCLRC;
13097                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13098
13099                         pic16_emitcode("clrc","");
13100                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13101                                 AOP(right)->aopu.aop_dir,
13102                                 AOP(right)->aopu.aop_dir);
13103                         pic16_aopPut(AOP(result),"c",0);
13104                         goto release ;
13105                 }
13106
13107                 /* we need to or */
13108                 if (AOP_TYPE(right) == AOP_REG) {
13109                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13110                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13111                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13112                 }
13113                 pic16_toBoolean(right);
13114                 pic16_aopPut(AOP(result),"a",0);
13115                 goto release ;
13116         }
13117
13118         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13119           int offset = 1;
13120
13121                 size = AOP_SIZE(result);
13122
13123                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13124
13125                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13126                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13127                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13128
13129                 while (size--)
13130                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13131
13132                 goto release;
13133         }
13134
13135         if(IS_BITFIELD(getSpec(restype))
13136           && IS_BITFIELD(getSpec(rtype))) {
13137           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13138         }
13139
13140         /* port from pic14 to cope with generic pointers */
13141         if (PIC_IS_TAGGED(restype))
13142         {
13143           operand *result = IC_RESULT(ic);
13144           //operand *left = IC_LEFT(ic);
13145           operand *right = IC_RIGHT(ic);
13146           int tag = 0xff;
13147
13148           /* copy common part */
13149           int max, size = AOP_SIZE(result);
13150           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13151           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13152
13153           max = size;
13154           while (size--)
13155           {
13156             pic16_mov2w (AOP(right), size);
13157             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13158           } // while
13159
13160           /* upcast into generic pointer type? */
13161           if (IS_GENPTR(restype)
13162               && !PIC_IS_TAGGED(rtype)
13163               && (AOP_SIZE(result) > max))
13164           {
13165             /* determine appropriate tag for right */
13166             if (PIC_IS_DATA_PTR(rtype))
13167               tag = GPTR_TAG_DATA;
13168             else if (IS_CODEPTR(rtype))
13169               tag = GPTR_TAG_CODE;
13170             else if (PIC_IS_DATA_PTR(ctype)) {
13171               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13172               tag = GPTR_TAG_DATA;
13173             } else if (IS_CODEPTR(ctype)) {
13174               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13175               tag = GPTR_TAG_CODE;
13176             } else if (IS_PTR(rtype)) {
13177               PERFORM_ONCE(weirdcast,
13178               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13179               );
13180               tag = GPTR_TAG_DATA;
13181             } else {
13182               PERFORM_ONCE(weirdcast,
13183               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13184               );
13185               tag = GPTR_TAG_DATA;
13186             }
13187
13188             assert (AOP_SIZE(result) == 3);
13189             /* zero-extend address... */
13190             for (size = max; size < AOP_SIZE(result)-1; size++)
13191               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13192             /* ...and add tag */
13193             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13194           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13195             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13196             for (size = max; size < AOP_SIZE(result)-1; size++)
13197               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13198             /* add __code tag */
13199             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13200           } else if (AOP_SIZE(result) > max) {
13201             /* extend non-pointers */
13202             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13203             pic16_addSign(result, max, 0);
13204           } // if
13205           goto release;
13206         }
13207
13208         /* if they are the same size : or less */
13209         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13210
13211                 /* if they are in the same place */
13212                 if (pic16_sameRegs(AOP(right),AOP(result)))
13213                         goto release;
13214
13215                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13216 #if 0
13217                 if (IS_PTR_CONST(rtype))
13218 #else
13219                 if (IS_CODEPTR(rtype))
13220 #endif
13221                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13222
13223 #if 0
13224                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13225 #else
13226                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13227 #endif
13228                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13229
13230 #if 0
13231                 if(AOP_TYPE(right) == AOP_IMMD) {
13232                   pCodeOp *pcop0, *pcop1, *pcop2;
13233                   symbol *sym = OP_SYMBOL( right );
13234
13235                         size = AOP_SIZE(result);
13236                         /* low */
13237                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13238                         /* high */
13239                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13240                         /* upper */
13241                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13242
13243                         if (size == 3) {
13244                                 pic16_emitpcode(POC_MOVLW, pcop0);
13245                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13246                                 pic16_emitpcode(POC_MOVLW, pcop1);
13247                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13248                                 pic16_emitpcode(POC_MOVLW, pcop2);
13249                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13250                         } else
13251                         if (size == 2) {
13252                                 pic16_emitpcode(POC_MOVLW, pcop0);
13253                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13254                                 pic16_emitpcode(POC_MOVLW, pcop1);
13255                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13256                         } else {
13257                                 pic16_emitpcode(POC_MOVLW, pcop0);
13258                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13259                         }
13260                 } else
13261 #endif
13262                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13263                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13264                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13265
13266                         if(AOP_SIZE(result) < 2) {
13267                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13268                         } else {
13269                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13270                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13271                         }
13272                 } else {
13273                         /* if they in different places then copy */
13274                         size = AOP_SIZE(result);
13275                         offset = 0 ;
13276                         while (size--) {
13277                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13278                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13279                                 offset++;
13280                         }
13281                 }
13282                 goto release;
13283         }
13284
13285         /* if the result is of type pointer */
13286         if (IS_PTR(ctype)) {
13287           int p_type;
13288           sym_link *type = operandType(right);
13289           sym_link *etype = getSpec(type);
13290
13291                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13292
13293                 /* pointer to generic pointer */
13294                 if (IS_GENPTR(ctype)) {
13295                   char *l = zero;
13296
13297                         if (IS_PTR(type))
13298                                 p_type = DCL_TYPE(type);
13299                         else {
13300                 /* we have to go by the storage class */
13301                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13302
13303 /*              if (SPEC_OCLS(etype)->codesp )  */
13304 /*                  p_type = CPOINTER ;  */
13305 /*              else */
13306 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13307 /*                      p_type = FPOINTER ; */
13308 /*                  else */
13309 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13310 /*                          p_type = PPOINTER; */
13311 /*                      else */
13312 /*                          if (SPEC_OCLS(etype) == idata ) */
13313 /*                              p_type = IPOINTER ; */
13314 /*                          else */
13315 /*                              p_type = POINTER ; */
13316             }
13317
13318             /* the first two bytes are known */
13319       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13320             size = GPTRSIZE - 1;
13321             offset = 0 ;
13322             while (size--) {
13323               if(offset < AOP_SIZE(right)) {
13324                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13325                 pic16_mov2f(AOP(result), AOP(right), offset);
13326 /*
13327                 if ((AOP_TYPE(right) == AOP_PCODE) &&
13328                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13329                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13330                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13331                 } else {
13332
13333                   pic16_aopPut(AOP(result),
13334                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13335                          offset);
13336                 }
13337 */
13338               } else
13339                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13340               offset++;
13341             }
13342             /* the last byte depending on type */
13343             switch (p_type) {
13344             case IPOINTER:
13345             case POINTER:
13346             case FPOINTER:
13347                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13348                 break;
13349
13350             case CPOINTER:
13351                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13352                 break;
13353
13354             case PPOINTER:
13355               pic16_emitcode(";BUG!? ","%d",__LINE__);
13356                 l = "#0x03";
13357                 break;
13358
13359             case GPOINTER:
13360                 if (GPTRSIZE > AOP_SIZE(right)) {
13361                   // assume __data pointer... THIS MIGHT BE WRONG!
13362                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13363                 } else {
13364                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13365                 }
13366               break;
13367
13368             default:
13369                 /* this should never happen */
13370                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13371                        "got unknown pointer type");
13372                 exit(1);
13373             }
13374             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13375             goto release ;
13376         }
13377
13378
13379         assert( 0 );
13380         /* just copy the pointers */
13381         size = AOP_SIZE(result);
13382         offset = 0 ;
13383         while (size--) {
13384             pic16_aopPut(AOP(result),
13385                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13386                    offset);
13387             offset++;
13388         }
13389         goto release ;
13390     }
13391
13392
13393
13394     /* so we now know that the size of destination is greater
13395     than the size of the source.
13396     Now, if the next iCode is an operator then we might be
13397     able to optimize the operation without performing a cast.
13398     */
13399     if(genMixedOperation(ic))
13400       goto release;
13401
13402     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13403
13404     /* we move to result for the size of source */
13405     size = AOP_SIZE(right);
13406     offset = 0 ;
13407
13408     while (size--) {
13409       if(!_G.resDirect)
13410         pic16_mov2f(AOP(result), AOP(right), offset);
13411       offset++;
13412     }
13413
13414     /* now depending on the sign of the destination */
13415     size = AOP_SIZE(result) - AOP_SIZE(right);
13416     /* if unsigned or not an integral type */
13417     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13418       while (size--)
13419         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13420     } else {
13421       /* we need to extend the sign :( */
13422
13423       if(size == 1) {
13424         /* Save one instruction of casting char to int */
13425         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13426         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13427         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13428       } else {
13429         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13430
13431         if(offset)
13432           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13433         else
13434           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13435
13436         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13437
13438         while (size--)
13439           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13440       }
13441     }
13442
13443 release:
13444     pic16_freeAsmop(right,NULL,ic,TRUE);
13445     pic16_freeAsmop(result,NULL,ic,TRUE);
13446
13447 }
13448
13449 /*-----------------------------------------------------------------*/
13450 /* genDjnz - generate decrement & jump if not zero instrucion      */
13451 /*-----------------------------------------------------------------*/
13452 static int genDjnz (iCode *ic, iCode *ifx)
13453 {
13454     symbol *lbl, *lbl1;
13455     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13456
13457     if (!ifx)
13458         return 0;
13459
13460     /* if the if condition has a false label
13461        then we cannot save */
13462     if (IC_FALSE(ifx))
13463         return 0;
13464
13465     /* if the minus is not of the form
13466        a = a - 1 */
13467     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13468         !IS_OP_LITERAL(IC_RIGHT(ic)))
13469         return 0;
13470
13471     if (operandLitValue(IC_RIGHT(ic)) != 1)
13472         return 0;
13473
13474     /* if the size of this greater than one then no
13475        saving */
13476     if (getSize(operandType(IC_RESULT(ic))) > 1)
13477         return 0;
13478
13479     /* otherwise we can save BIG */
13480     lbl = newiTempLabel(NULL);
13481     lbl1= newiTempLabel(NULL);
13482
13483     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13484
13485     if (IS_AOP_PREG(IC_RESULT(ic))) {
13486         pic16_emitcode("dec","%s",
13487                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13488         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13489         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13490     } else {
13491
13492
13493       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13494       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13495
13496       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13497       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13498
13499     }
13500
13501     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13502     ifx->generated = 1;
13503     return 1;
13504 }
13505
13506 /*-----------------------------------------------------------------*/
13507 /* genReceive - generate code for a receive iCode                  */
13508 /*-----------------------------------------------------------------*/
13509 static void genReceive (iCode *ic)
13510 {
13511
13512   FENTRY;
13513
13514 #if 0
13515   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13516         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13517 #endif
13518 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13519
13520   if (isOperandInFarSpace(IC_RESULT(ic))
13521       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13522           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13523
13524     int size = getSize(operandType(IC_RESULT(ic)));
13525     int offset =  pic16_fReturnSizePic - size;
13526
13527       assert( 0 );
13528       while (size--) {
13529         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13530                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13531                       offset++;
13532         }
13533
13534       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13535
13536       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13537       size = AOP_SIZE(IC_RESULT(ic));
13538       offset = 0;
13539       while (size--) {
13540         pic16_emitcode ("pop","acc");
13541         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13542       }
13543   } else {
13544     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13545     _G.accInUse++;
13546     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13547     _G.accInUse--;
13548
13549     /* set pseudo stack pointer to where it should be - dw*/
13550     GpsuedoStkPtr = ic->parmBytes;
13551
13552     /* setting GpsuedoStkPtr has side effects here: */
13553     /* FIXME: What's the correct size of the return(ed) value?
13554      *        For now, assuming '4' as before... */
13555     assignResultValue(IC_RESULT(ic), 4, 0);
13556   }
13557
13558   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13559 }
13560
13561 /*-----------------------------------------------------------------*/
13562 /* genDummyRead - generate code for dummy read of volatiles        */
13563 /*-----------------------------------------------------------------*/
13564 static void
13565 genDummyRead (iCode * ic)
13566 {
13567   operand *op;
13568   int i;
13569
13570   op = IC_RIGHT(ic);
13571   if (op && IS_SYMOP(op)) {
13572     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13573       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13574       return;
13575     }
13576     pic16_aopOp (op, ic, FALSE);
13577     for (i=0; i < AOP_SIZE(op); i++) {
13578       // may need to protect this from the peepholer -- this is not nice but works...
13579       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13580       pic16_mov2w (AOP(op),i);
13581       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13582     } // for i
13583     pic16_freeAsmop (op, NULL, ic, TRUE);
13584   } else if (op) {
13585     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13586   } // if
13587 }
13588
13589 /*-----------------------------------------------------------------*/
13590 /* genpic16Code - generate code for pic16 based controllers        */
13591 /*-----------------------------------------------------------------*/
13592 /*
13593  * At this point, ralloc.c has gone through the iCode and attempted
13594  * to optimize in a way suitable for a PIC. Now we've got to generate
13595  * PIC instructions that correspond to the iCode.
13596  *
13597  * Once the instructions are generated, we'll pass through both the
13598  * peep hole optimizer and the pCode optimizer.
13599  *-----------------------------------------------------------------*/
13600
13601 void genpic16Code (iCode *lic)
13602 {
13603   iCode *ic;
13604   int cln = 0;
13605
13606     lineHead = lineCurr = NULL;
13607
13608     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13609     pic16_addpBlock(pb);
13610
13611 #if 0
13612     /* if debug information required */
13613     if (options.debug && currFunc) {
13614       if (currFunc) {
13615         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13616       }
13617     }
13618 #endif
13619
13620     for (ic = lic ; ic ; ic = ic->next ) {
13621
13622       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13623       if ( cln != ic->lineno ) {
13624         if ( options.debug ) {
13625           debugFile->writeCLine (ic);
13626         }
13627
13628         if(!options.noCcodeInAsm) {
13629           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13630               printCLine(ic->filename, ic->lineno)));
13631         }
13632
13633         cln = ic->lineno ;
13634       }
13635
13636       if(options.iCodeInAsm) {
13637         const char *iLine;
13638
13639         /* insert here code to print iCode as comment */
13640         iLine = printILine(ic);
13641         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13642         dbuf_free(iLine);
13643       }
13644
13645       /* if the result is marked as
13646        * spilt and rematerializable or code for
13647        * this has already been generated then
13648        * do nothing */
13649       if (resultRemat(ic) || ic->generated )
13650         continue ;
13651
13652       /* depending on the operation */
13653       switch (ic->op) {
13654         case '!' :
13655           pic16_genNot(ic);
13656           break;
13657
13658         case '~' :
13659           pic16_genCpl(ic);
13660           break;
13661
13662         case UNARYMINUS:
13663           genUminus (ic);
13664           break;
13665
13666         case IPUSH:
13667           genIpush (ic);
13668           break;
13669
13670         case IPOP:
13671           /* IPOP happens only when trying to restore a
13672            * spilt live range, if there is an ifx statement
13673            * following this pop then the if statement might
13674            * be using some of the registers being popped which
13675            * would destroy the contents of the register so
13676            * we need to check for this condition and handle it */
13677            if (ic->next
13678              && ic->next->op == IFX
13679              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13680                genIfx (ic->next,ic);
13681           else
13682             genIpop (ic);
13683           break;
13684
13685         case CALL:
13686           genCall (ic);
13687           break;
13688
13689         case PCALL:
13690           genPcall (ic);
13691           break;
13692
13693         case FUNCTION:
13694           genFunction (ic);
13695           break;
13696
13697         case ENDFUNCTION:
13698           genEndFunction (ic);
13699           break;
13700
13701         case RETURN:
13702           genRet (ic);
13703           break;
13704
13705         case LABEL:
13706           genLabel (ic);
13707           break;
13708
13709         case GOTO:
13710           genGoto (ic);
13711           break;
13712
13713         case '+' :
13714           pic16_genPlus (ic) ;
13715           break;
13716
13717         case '-' :
13718           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13719             pic16_genMinus (ic);
13720           break;
13721
13722         case '*' :
13723           genMult (ic);
13724           break;
13725
13726         case '/' :
13727           genDiv (ic) ;
13728           break;
13729
13730         case '%' :
13731           genMod (ic);
13732           break;
13733
13734         case '>' :
13735           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13736           break;
13737
13738         case '<' :
13739           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13740           break;
13741
13742         case LE_OP:
13743         case GE_OP:
13744         case NE_OP:
13745           /* note these two are xlated by algebraic equivalence
13746            * during parsing SDCC.y */
13747           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13748             "got '>=' or '<=' shouldn't have come here");
13749           break;
13750
13751         case EQ_OP:
13752           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13753           break;
13754
13755         case AND_OP:
13756           genAndOp (ic);
13757           break;
13758
13759         case OR_OP:
13760           genOrOp (ic);
13761           break;
13762
13763         case '^' :
13764           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13765           break;
13766
13767         case '|' :
13768           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13769           break;
13770
13771         case BITWISEAND:
13772           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13773           break;
13774
13775         case INLINEASM:
13776           genInline (ic);
13777           break;
13778
13779         case RRC:
13780           genRRC (ic);
13781           break;
13782
13783         case RLC:
13784           genRLC (ic);
13785           break;
13786
13787         case GETHBIT:
13788           genGetHbit (ic);
13789           break;
13790
13791         case LEFT_OP:
13792           genLeftShift (ic);
13793           break;
13794
13795         case RIGHT_OP:
13796           genRightShift (ic);
13797           break;
13798
13799         case GET_VALUE_AT_ADDRESS:
13800           genPointerGet(ic);
13801           break;
13802
13803         case '=' :
13804           if (POINTER_SET(ic))
13805             genPointerSet(ic);
13806           else
13807             genAssign(ic);
13808           break;
13809
13810         case IFX:
13811           genIfx (ic,NULL);
13812           break;
13813
13814         case ADDRESS_OF:
13815           genAddrOf (ic);
13816           break;
13817
13818         case JUMPTABLE:
13819           genJumpTab (ic);
13820           break;
13821
13822         case CAST:
13823           genCast (ic);
13824           break;
13825
13826         case RECEIVE:
13827           genReceive(ic);
13828           break;
13829
13830         case SEND:
13831           addSet(&_G.sendSet,ic);
13832           break;
13833
13834         case DUMMY_READ_VOLATILE:
13835           genDummyRead (ic);
13836           break;
13837
13838         default :
13839           ic = ic;
13840       }
13841     }
13842
13843
13844     /* now we are ready to call the
13845        peep hole optimizer */
13846     if (!options.nopeep)
13847       peepHole (&lineHead);
13848
13849     /* now do the actual printing */
13850     printLine (lineHead, codeOutBuf);
13851
13852 #ifdef PCODE_DEBUG
13853     DFPRINTF((stderr,"printing pBlock\n\n"));
13854     pic16_printpBlock(stdout,pb);
13855 #endif
13856
13857     return;
13858 }