* src/pic16/gen.c: fixed implementation of bitwise operations for
[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         switch(shCount){
8913                 case 0 :
8914                         return; break;
8915                 case 1 :
8916                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8917                         break;
8918                 case 2 :
8919                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8920                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8921                         break;
8922                 case 3 :
8923                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8924                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8925                         break;
8926                 case 4 :
8927                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8928                         break;
8929                 case 5 :
8930                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8931                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8932                         break;
8933                 case 6 :
8934                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8935                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8936                         break;
8937                 case 7 :
8938                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8939                         break;
8940         }
8941
8942         if(andmask)
8943                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8944         else
8945                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8946 }
8947
8948 #if 0
8949 /*-----------------------------------------------------------------*/
8950 /* AccSRsh - signed right shift accumulator by known count                 */
8951 /*-----------------------------------------------------------------*/
8952 static void AccSRsh (int shCount)
8953 {
8954     symbol *tlbl ;
8955     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8956     if(shCount != 0){
8957         if(shCount == 1){
8958             pic16_emitcode("mov","c,acc.7");
8959             pic16_emitcode("rrc","a");
8960         } else if(shCount == 2){
8961             pic16_emitcode("mov","c,acc.7");
8962             pic16_emitcode("rrc","a");
8963             pic16_emitcode("mov","c,acc.7");
8964             pic16_emitcode("rrc","a");
8965         } else {
8966             tlbl = newiTempLabel(NULL);
8967             /* rotate right accumulator */
8968             AccRol(8 - shCount);
8969             /* and kill the higher order bits */
8970             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8971             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8972             pic16_emitcode("orl","a,#0x%02x",
8973                      (unsigned char)~SRMask[shCount]);
8974             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8975         }
8976     }
8977 }
8978 #endif
8979
8980 /*-----------------------------------------------------------------*/
8981 /* shiftR1Left2Result - shift right one byte from left to result   */
8982 /*-----------------------------------------------------------------*/
8983 static void shiftR1Left2ResultSigned (operand *left, int offl,
8984                                 operand *result, int offr,
8985                                 int shCount)
8986 {
8987   int same;
8988
8989   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8990
8991   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8992
8993   switch(shCount) {
8994   case 1:
8995     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8996     if(same)
8997       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8998     else {
8999       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9000       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9001     }
9002
9003     break;
9004   case 2:
9005
9006     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9007     if(same)
9008       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9009     else {
9010       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9012     }
9013     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9014     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9015
9016     break;
9017
9018   case 3:
9019     if(same)
9020       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9021     else {
9022       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9023       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9024     }
9025
9026     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9027     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9028     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9029
9030     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9031     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
9032
9033     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034     break;
9035
9036   case 4:
9037     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9038     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
9039     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9040     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
9041     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9042     break;
9043   case 5:
9044     if(same) {
9045       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
9046     } else {
9047       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
9048       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9049     }
9050     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
9051     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
9052     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
9053     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
9054     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9055     break;
9056
9057   case 6:
9058     if(same) {
9059       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9060       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9061       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
9062       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9063       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
9064       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9065     } else {
9066       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9067       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9068       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
9069       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
9070       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9071     }
9072     break;
9073
9074   case 7:
9075     if(same) {
9076       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
9077       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9078       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9079       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9080     } else {
9081       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
9082       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9083       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
9084     }
9085
9086   default:
9087     break;
9088   }
9089 }
9090
9091 /*-----------------------------------------------------------------*/
9092 /* shiftR1Left2Result - shift right one byte from left to result   */
9093 /*-----------------------------------------------------------------*/
9094 static void shiftR1Left2Result (operand *left, int offl,
9095                                 operand *result, int offr,
9096                                 int shCount, int sign)
9097 {
9098   int same;
9099
9100   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9101
9102   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9103
9104   /* Copy the msb into the carry if signed. */
9105   if(sign) {
9106     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9107     return;
9108   }
9109
9110
9111
9112   switch(shCount) {
9113   case 1:
9114     emitCLRC;
9115     if(same)
9116       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9117     else {
9118       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9119       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9120     }
9121     break;
9122   case 2:
9123     emitCLRC;
9124     if(same) {
9125       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9126     } else {
9127       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9128       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9129     }
9130     emitCLRC;
9131     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9132
9133     break;
9134   case 3:
9135     if(same)
9136       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9137     else {
9138       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9139       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9140     }
9141
9142     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9143     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9144     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9145     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9146     break;
9147
9148   case 4:
9149     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9150     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9151     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9152     break;
9153
9154   case 5:
9155     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9156     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9157     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9158     //emitCLRC;
9159     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9160
9161     break;
9162   case 6:
9163
9164     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9165     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9166     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9167     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9168     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9169     break;
9170
9171   case 7:
9172
9173     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9174     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9175     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9176
9177     break;
9178
9179   default:
9180     break;
9181   }
9182 }
9183
9184 /*-----------------------------------------------------------------*/
9185 /* shiftL1Left2Result - shift left one byte from left to result    */
9186 /*-----------------------------------------------------------------*/
9187 static void shiftL1Left2Result (operand *left, int offl,
9188                                 operand *result, int offr, int shCount)
9189 {
9190   int same;
9191
9192   //    char *l;
9193   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9194
9195   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9196   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9197     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9198     //    MOVA(l);
9199     /* shift left accumulator */
9200     //AccLsh(shCount, 1); // don't comment out just yet...
9201   //    pic16_aopPut(AOP(result),"a",offr);
9202
9203   switch(shCount) {
9204   case 1:
9205     /* Shift left 1 bit position */
9206     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9207     if(same) {
9208       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9209     } else {
9210       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9211       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9212     }
9213     break;
9214   case 2:
9215     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9216     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9217     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9218     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9219     break;
9220   case 3:
9221     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9222     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9223     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9224     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9225     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9226     break;
9227   case 4:
9228     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9229     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9230     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9231     break;
9232   case 5:
9233     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9234     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9235     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9236     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9237     break;
9238   case 6:
9239     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9240     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9241     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9242     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9243     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9244     break;
9245   case 7:
9246     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9247     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9248     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9249     break;
9250
9251   default:
9252     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9253   }
9254
9255 }
9256
9257 /*-----------------------------------------------------------------*/
9258 /* movLeft2Result - move byte from left to result                  */
9259 /*-----------------------------------------------------------------*/
9260 static void movLeft2Result (operand *left, int offl,
9261                             operand *result, int offr)
9262 {
9263   char *l;
9264   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9265   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9266     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9267
9268     if (*l == '@' && (IS_AOP_PREG(result))) {
9269       pic16_emitcode("mov","a,%s",l);
9270       pic16_aopPut(AOP(result),"a",offr);
9271     } else {
9272       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9273       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9274     }
9275   }
9276 }
9277
9278 /*-----------------------------------------------------------------*/
9279 /* shiftL2Left2Result - shift left two bytes from left to result   */
9280 /*-----------------------------------------------------------------*/
9281 static void shiftL2Left2Result (operand *left, int offl,
9282                                 operand *result, int offr, int shCount)
9283 {
9284   int same = pic16_sameRegs(AOP(result), AOP(left));
9285   int i;
9286
9287   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9288
9289   if (same && (offl != offr)) { // shift bytes
9290     if (offr > offl) {
9291        for(i=1;i>-1;i--) {
9292          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9293          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9294        }
9295     } else { // just treat as different later on
9296                 same = 0;
9297     }
9298   }
9299
9300   if(same) {
9301     switch(shCount) {
9302     case 0:
9303       break;
9304     case 1:
9305     case 2:
9306     case 3:
9307
9308       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9309       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9310       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9311
9312       while(--shCount) {
9313                 emitCLRC;
9314                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9315                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9316       }
9317
9318       break;
9319     case 4:
9320     case 5:
9321       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9322       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9323       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9324       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9325       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9326       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9327       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9328       if(shCount >=5) {
9329                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9330                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9331       }
9332       break;
9333     case 6:
9334       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9335       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9336       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9337       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9338       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9339       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9340       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9341       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9342       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9343       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9344       break;
9345     case 7:
9346       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9347       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9348       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9349       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9350       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9351     }
9352
9353   } else {
9354     switch(shCount) {
9355     case 0:
9356       break;
9357     case 1:
9358     case 2:
9359     case 3:
9360       /* note, use a mov/add for the shift since the mov has a
9361          chance of getting optimized out */
9362       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9363       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9364       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9365       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9366       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9367
9368       while(--shCount) {
9369                 emitCLRC;
9370                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9371                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9372       }
9373       break;
9374
9375     case 4:
9376     case 5:
9377       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9378       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9379       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9380       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9382       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9383       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9384       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9385
9386
9387       if(shCount == 5) {
9388                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9389                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9390       }
9391       break;
9392     case 6:
9393       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9394       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9395       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9396       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9397
9398       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9399       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9400       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9401       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9402       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9403       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9404       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9405       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9406       break;
9407     case 7:
9408       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9409       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9410       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9411       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9412       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9413     }
9414   }
9415
9416 }
9417 /*-----------------------------------------------------------------*/
9418 /* shiftR2Left2Result - shift right two bytes from left to result  */
9419 /*-----------------------------------------------------------------*/
9420 static void shiftR2Left2Result (operand *left, int offl,
9421                                 operand *result, int offr,
9422                                 int shCount, int sign)
9423 {
9424   int same = pic16_sameRegs(AOP(result), AOP(left));
9425   int i;
9426   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9427
9428   if (same && (offl != offr)) { // shift right bytes
9429     if (offr < offl) {
9430        for(i=0;i<2;i++) {
9431          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9432          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9433        }
9434     } else { // just treat as different later on
9435                 same = 0;
9436     }
9437   }
9438
9439   switch(shCount) {
9440   case 0:
9441     break;
9442   case 1:
9443   case 2:
9444   case 3:
9445     /* obtain sign from left operand */
9446     if(sign)
9447       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9448     else
9449       emitCLRC;
9450
9451     if(same) {
9452       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9453       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9454     } else {
9455       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9456       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9457       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9458       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9459     }
9460
9461     while(--shCount) {
9462       if(sign)
9463         /* now get sign from already assigned result (avoid BANKSEL) */
9464         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9465       else
9466         emitCLRC;
9467       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9468       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9469     }
9470     break;
9471   case 4:
9472   case 5:
9473     if(same) {
9474
9475       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9476       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9477       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9478
9479       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9480       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9481       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9482       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9483     } else {
9484       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9485       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9486       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9487
9488       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9489       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9490       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9491       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9492       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9493     }
9494
9495     if(shCount >=5) {
9496       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9497       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9498     }
9499
9500     if(sign) {
9501       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9502       pic16_emitpcode(POC_BTFSC,
9503                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9504       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9505     }
9506
9507     break;
9508
9509   case 6:
9510     if(same) {
9511
9512       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9513       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9514
9515       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9516       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9517       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9518       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9519       if(sign) {
9520         pic16_emitpcode(POC_BTFSC,
9521                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9522         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9523       }
9524       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9525       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9526       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9527       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9528     } else {
9529       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9530       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9531       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9532       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9533       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9534       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9535       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9536       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9537       if(sign) {
9538         pic16_emitpcode(POC_BTFSC,
9539                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9540         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9541       }
9542       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9543       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9544
9545
9546     }
9547
9548     break;
9549   case 7:
9550     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9551     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9552     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9553     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9554     if(sign) {
9555       emitSKPNC;
9556       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9557     } else
9558       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9559   }
9560 }
9561
9562
9563 /*-----------------------------------------------------------------*/
9564 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9565 /*-----------------------------------------------------------------*/
9566 static void shiftLLeftOrResult (operand *left, int offl,
9567                                 operand *result, int offr, int shCount)
9568 {
9569     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9570
9571     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9572     /* shift left accumulator */
9573     AccLsh(shCount, 1);
9574     /* or with result */
9575     /* back to result */
9576     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9577 }
9578
9579 /*-----------------------------------------------------------------*/
9580 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9581 /*-----------------------------------------------------------------*/
9582 static void shiftRLeftOrResult (operand *left, int offl,
9583                                 operand *result, int offr, int shCount)
9584 {
9585     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9586
9587     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9588     /* shift right accumulator */
9589     AccRsh(shCount, 1);
9590     /* or with result */
9591     /* back to result */
9592     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9593 }
9594
9595 /*-----------------------------------------------------------------*/
9596 /* genlshOne - left shift a one byte quantity by known count       */
9597 /*-----------------------------------------------------------------*/
9598 static void genlshOne (operand *result, operand *left, int shCount)
9599 {
9600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9601     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9602 }
9603
9604 /*-----------------------------------------------------------------*/
9605 /* genlshTwo - left shift two bytes by known amount != 0           */
9606 /*-----------------------------------------------------------------*/
9607 static void genlshTwo (operand *result,operand *left, int shCount)
9608 {
9609     int size;
9610
9611     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9612     size = pic16_getDataSize(result);
9613
9614     /* if shCount >= 8 */
9615     if (shCount >= 8) {
9616         shCount -= 8 ;
9617
9618         if (size > 1){
9619             if (shCount)
9620                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9621             else
9622                 movLeft2Result(left, LSB, result, MSB16);
9623         }
9624         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9625     }
9626
9627     /*  1 <= shCount <= 7 */
9628     else {
9629         if(size == 1)
9630             shiftL1Left2Result(left, LSB, result, LSB, shCount);
9631         else
9632             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9633     }
9634 }
9635
9636 /*-----------------------------------------------------------------*/
9637 /* shiftLLong - shift left one long from left to result            */
9638 /* offr = LSB or MSB16                                             */
9639 /*-----------------------------------------------------------------*/
9640 static void shiftLLong (operand *left, operand *result, int offr )
9641 {
9642     int size = AOP_SIZE(result);
9643     int same = pic16_sameRegs(AOP(left),AOP(result));
9644         int i;
9645
9646     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9647
9648         if (same && (offr == MSB16)) { //shift one byte
9649                 for(i=size-1;i>=MSB16;i--) {
9650                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9651                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9652                 }
9653         } else {
9654                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9655         }
9656
9657     if (size > LSB+offr ){
9658                 if (same) {
9659                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9660                 } else {
9661                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9662                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9663                 }
9664          }
9665
9666     if(size > MSB16+offr){
9667                 if (same) {
9668                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9669                 } else {
9670                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9671                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9672                 }
9673     }
9674
9675     if(size > MSB24+offr){
9676                 if (same) {
9677                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9678                 } else {
9679                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9680                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9681                 }
9682     }
9683
9684     if(size > MSB32+offr){
9685                 if (same) {
9686                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9687                 } else {
9688                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9689                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9690                 }
9691     }
9692     if(offr != LSB)
9693                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9694
9695 }
9696
9697 /*-----------------------------------------------------------------*/
9698 /* genlshFour - shift four byte by a known amount != 0             */
9699 /*-----------------------------------------------------------------*/
9700 static void genlshFour (operand *result, operand *left, int shCount)
9701 {
9702     int size;
9703
9704     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9705     size = AOP_SIZE(result);
9706
9707     /* if shifting more that 3 bytes */
9708     if (shCount >= 24 ) {
9709         shCount -= 24;
9710         if (shCount)
9711             /* lowest order of left goes to the highest
9712             order of the destination */
9713             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9714         else
9715             movLeft2Result(left, LSB, result, MSB32);
9716
9717                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9718                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9719                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9720
9721         return;
9722     }
9723
9724     /* more than two bytes */
9725     else if ( shCount >= 16 ) {
9726         /* lower order two bytes goes to higher order two bytes */
9727         shCount -= 16;
9728         /* if some more remaining */
9729         if (shCount)
9730             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9731         else {
9732             movLeft2Result(left, MSB16, result, MSB32);
9733             movLeft2Result(left, LSB, result, MSB24);
9734         }
9735                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9736                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9737         return;
9738     }
9739
9740     /* if more than 1 byte */
9741     else if ( shCount >= 8 ) {
9742         /* lower order three bytes goes to higher order  three bytes */
9743         shCount -= 8;
9744         if(size == 2){
9745             if(shCount)
9746                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9747             else
9748                 movLeft2Result(left, LSB, result, MSB16);
9749         }
9750         else{   /* size = 4 */
9751             if(shCount == 0){
9752                 movLeft2Result(left, MSB24, result, MSB32);
9753                 movLeft2Result(left, MSB16, result, MSB24);
9754                 movLeft2Result(left, LSB, result, MSB16);
9755                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9756             }
9757             else if(shCount == 1)
9758                 shiftLLong(left, result, MSB16);
9759             else{
9760                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9761                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9762                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9763                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9764             }
9765         }
9766     }
9767
9768     /* 1 <= shCount <= 7 */
9769     else if(shCount <= 3)
9770     {
9771         shiftLLong(left, result, LSB);
9772         while(--shCount >= 1)
9773             shiftLLong(result, result, LSB);
9774     }
9775     /* 3 <= shCount <= 7, optimize */
9776     else{
9777         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9778         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9779         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9780     }
9781 }
9782
9783 /*-----------------------------------------------------------------*/
9784 /* genLeftShiftLiteral - left shifting by known count              */
9785 /*-----------------------------------------------------------------*/
9786 void pic16_genLeftShiftLiteral (operand *left,
9787                                  operand *right,
9788                                  operand *result,
9789                                  iCode *ic)
9790 {
9791     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
9792     int size;
9793
9794     FENTRY;
9795     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9796     pic16_freeAsmop(right,NULL,ic,TRUE);
9797
9798     pic16_aopOp(left,ic,FALSE);
9799     pic16_aopOp(result,ic,TRUE);
9800
9801     size = getSize(operandType(result));
9802
9803 #if VIEW_SIZE
9804     pic16_emitcode("; shift left ","result %d, left %d",size,
9805              AOP_SIZE(left));
9806 #endif
9807
9808     /* I suppose that the left size >= result size */
9809     if(shCount == 0){
9810         while(size--){
9811             movLeft2Result(left, size, result, size);
9812         }
9813     }
9814
9815     else if(shCount >= (size * 8))
9816         while(size--)
9817             pic16_aopPut(AOP(result),zero,size);
9818     else{
9819         switch (size) {
9820             case 1:
9821                 genlshOne (result,left,shCount);
9822                 break;
9823
9824             case 2:
9825             case 3:
9826                 genlshTwo (result,left,shCount);
9827                 break;
9828
9829             case 4:
9830                 genlshFour (result,left,shCount);
9831                 break;
9832         }
9833     }
9834     pic16_freeAsmop(left,NULL,ic,TRUE);
9835     pic16_freeAsmop(result,NULL,ic,TRUE);
9836 }
9837
9838 /*-----------------------------------------------------------------*
9839  * genMultiAsm - repeat assembly instruction for size of register.
9840  * if endian == 1, then the high byte (i.e base address + size of
9841  * register) is used first else the low byte is used first;
9842  *-----------------------------------------------------------------*/
9843 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9844 {
9845
9846   int offset = 0;
9847
9848   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9849
9850   if(!reg)
9851     return;
9852
9853   if(!endian) {
9854     endian = 1;
9855   } else {
9856     endian = -1;
9857     offset = size-1;
9858   }
9859
9860   while(size--) {
9861     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9862     offset += endian;
9863   }
9864
9865 }
9866
9867 #if !(USE_GENERIC_SIGNED_SHIFT)
9868 /*-----------------------------------------------------------------*/
9869 /* genLeftShift - generates code for left shifting                 */
9870 /*-----------------------------------------------------------------*/
9871 static void genLeftShift (iCode *ic)
9872 {
9873   operand *left,*right, *result;
9874   int size, offset;
9875 //  char *l;
9876   symbol *tlbl , *tlbl1;
9877   pCodeOp *pctemp;
9878
9879   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9880
9881   right = IC_RIGHT(ic);
9882   left  = IC_LEFT(ic);
9883   result = IC_RESULT(ic);
9884
9885   pic16_aopOp(right,ic,FALSE);
9886
9887   /* if the shift count is known then do it
9888      as efficiently as possible */
9889   if (AOP_TYPE(right) == AOP_LIT) {
9890     pic16_genLeftShiftLiteral (left,right,result,ic);
9891     return ;
9892   }
9893
9894   /* shift count is unknown then we have to form
9895    * a loop. Get the loop count in WREG : Note: we take
9896    * only the lower order byte since shifting
9897    * more than 32 bits make no sense anyway, ( the
9898    * largest size of an object can be only 32 bits ) */
9899
9900   pic16_aopOp(left,ic,FALSE);
9901   pic16_aopOp(result,ic,FALSE);
9902
9903   /* now move the left to the result if they are not the
9904    * same, and if size > 1,
9905    * and if right is not same to result (!!!) -- VR */
9906   if (!pic16_sameRegs(AOP(left),AOP(result))
9907       && (AOP_SIZE(result) > 1)) {
9908
9909     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9910
9911     size = AOP_SIZE(result);
9912     offset=0;
9913     while (size--) {
9914
9915 #if 0
9916       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9917       if (*l == '@' && (IS_AOP_PREG(result))) {
9918
9919           pic16_emitcode("mov","a,%s",l);
9920           pic16_aopPut(AOP(result),"a",offset);
9921       } else
9922 #endif
9923       {
9924         /* we don't know if left is a literal or a register, take care -- VR */
9925         pic16_mov2f(AOP(result), AOP(left), offset);
9926       }
9927       offset++;
9928     }
9929   }
9930
9931   size = AOP_SIZE(result);
9932
9933   /* if it is only one byte then */
9934   if (size == 1) {
9935     if(optimized_for_speed) {
9936       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9937       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9938       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9939       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9940       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9941       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9942       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9943       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9944       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9945       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9946       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9947       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9948     } else {
9949
9950       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9951
9952       tlbl = newiTempLabel(NULL);
9953
9954 #if 1
9955       /* this is already done, why change it? */
9956       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9957                 pic16_mov2f(AOP(result), AOP(left), 0);
9958       }
9959 #endif
9960
9961       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9962       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9963       pic16_emitpLabel(tlbl->key);
9964       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9965       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9966       emitSKPC;
9967       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9968     }
9969     goto release ;
9970   }
9971
9972   if (pic16_sameRegs(AOP(left),AOP(result))) {
9973
9974     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9975
9976     tlbl = newiTempLabel(NULL);
9977     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9978     genMultiAsm(POC_RRCF, result, size,1);
9979     pic16_emitpLabel(tlbl->key);
9980     genMultiAsm(POC_RLCF, result, size,0);
9981     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9982     emitSKPC;
9983     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9984     goto release;
9985   }
9986
9987   //tlbl = newiTempLabel(NULL);
9988   //offset = 0 ;
9989   //tlbl1 = newiTempLabel(NULL);
9990
9991   //reAdjustPreg(AOP(result));
9992
9993   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9994   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9995   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9996   //MOVA(l);
9997   //pic16_emitcode("add","a,acc");
9998   //pic16_aopPut(AOP(result),"a",offset++);
9999   //while (--size) {
10000   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10001   //  MOVA(l);
10002   //  pic16_emitcode("rlc","a");
10003   //  pic16_aopPut(AOP(result),"a",offset++);
10004   //}
10005   //reAdjustPreg(AOP(result));
10006
10007   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10008   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10009
10010
10011   tlbl = newiTempLabel(NULL);
10012   tlbl1= newiTempLabel(NULL);
10013
10014   size = AOP_SIZE(result);
10015   offset = 1;
10016
10017   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10018
10019   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10020
10021   /* offset should be 0, 1 or 3 */
10022
10023   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10024   emitSKPNZ;
10025   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10026
10027   pic16_emitpcode(POC_MOVWF, pctemp);
10028
10029
10030   pic16_emitpLabel(tlbl->key);
10031
10032   emitCLRC;
10033   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10034   while(--size)
10035     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10036
10037   pic16_emitpcode(POC_DECFSZ,  pctemp);
10038   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10039   pic16_emitpLabel(tlbl1->key);
10040
10041   pic16_popReleaseTempReg(pctemp,1);
10042
10043
10044  release:
10045   pic16_freeAsmop (right,NULL,ic,TRUE);
10046   pic16_freeAsmop(left,NULL,ic,TRUE);
10047   pic16_freeAsmop(result,NULL,ic,TRUE);
10048 }
10049 #endif
10050
10051
10052 #if 0
10053 #error old code (left here for reference)
10054 /*-----------------------------------------------------------------*/
10055 /* genLeftShift - generates code for left shifting                 */
10056 /*-----------------------------------------------------------------*/
10057 static void genLeftShift (iCode *ic)
10058 {
10059   operand *left,*right, *result;
10060   int size, offset;
10061   char *l;
10062   symbol *tlbl , *tlbl1;
10063   pCodeOp *pctemp;
10064
10065   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10066
10067   right = IC_RIGHT(ic);
10068   left  = IC_LEFT(ic);
10069   result = IC_RESULT(ic);
10070
10071   pic16_aopOp(right,ic,FALSE);
10072
10073   /* if the shift count is known then do it
10074      as efficiently as possible */
10075   if (AOP_TYPE(right) == AOP_LIT) {
10076     pic16_genLeftShiftLiteral (left,right,result,ic);
10077     return ;
10078   }
10079
10080   /* shift count is unknown then we have to form
10081      a loop get the loop count in B : Note: we take
10082      only the lower order byte since shifting
10083      more that 32 bits make no sense anyway, ( the
10084      largest size of an object can be only 32 bits ) */
10085
10086
10087   pic16_aopOp(left,ic,FALSE);
10088   pic16_aopOp(result,ic,FALSE);
10089
10090   /* now move the left to the result if they are not the
10091      same */
10092   if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10093       AOP_SIZE(result) > 1) {
10094
10095     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10096
10097     size = AOP_SIZE(result);
10098     offset=0;
10099     while (size--) {
10100       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10101       if (*l == '@' && (IS_AOP_PREG(result))) {
10102
10103         pic16_emitcode("mov","a,%s",l);
10104         pic16_aopPut(AOP(result),"a",offset);
10105       } else {
10106
10107         /* we don't know if left is a literal or a register, take care -- VR */
10108         pic16_mov2f(AOP(result), AOP(left), offset);
10109       }
10110       offset++;
10111     }
10112   }
10113
10114   size = AOP_SIZE(result);
10115
10116   /* if it is only one byte then */
10117   if (size == 1) {
10118     if(optimized_for_speed) {
10119       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10120       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10121       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10122       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10123       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10124       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10125       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10126       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10127       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10128       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10129       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10130       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10131     } else {
10132
10133       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10134
10135       tlbl = newiTempLabel(NULL);
10136       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10137                 pic16_mov2f(AOP(result), AOP(left), 0);
10138
10139 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10140 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10141       }
10142
10143       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10144       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10145       pic16_emitpLabel(tlbl->key);
10146       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10147       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10148       emitSKPC;
10149       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10150     }
10151     goto release ;
10152   }
10153
10154   if (pic16_sameRegs(AOP(left),AOP(result))) {
10155
10156     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10157
10158     tlbl = newiTempLabel(NULL);
10159     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10160     genMultiAsm(POC_RRCF, result, size,1);
10161     pic16_emitpLabel(tlbl->key);
10162     genMultiAsm(POC_RLCF, result, size,0);
10163     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10164     emitSKPC;
10165     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10166     goto release;
10167   }
10168
10169   //tlbl = newiTempLabel(NULL);
10170   //offset = 0 ;
10171   //tlbl1 = newiTempLabel(NULL);
10172
10173   //reAdjustPreg(AOP(result));
10174
10175   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10176   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10177   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10178   //MOVA(l);
10179   //pic16_emitcode("add","a,acc");
10180   //pic16_aopPut(AOP(result),"a",offset++);
10181   //while (--size) {
10182   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10183   //  MOVA(l);
10184   //  pic16_emitcode("rlc","a");
10185   //  pic16_aopPut(AOP(result),"a",offset++);
10186   //}
10187   //reAdjustPreg(AOP(result));
10188
10189   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10190   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10191
10192
10193   tlbl = newiTempLabel(NULL);
10194   tlbl1= newiTempLabel(NULL);
10195
10196   size = AOP_SIZE(result);
10197   offset = 1;
10198
10199   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10200
10201   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10202
10203   /* offset should be 0, 1 or 3 */
10204
10205   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10206   emitSKPNZ;
10207   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10208
10209   pic16_emitpcode(POC_MOVWF, pctemp);
10210
10211
10212   pic16_emitpLabel(tlbl->key);
10213
10214   emitCLRC;
10215   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10216   while(--size)
10217     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10218
10219   pic16_emitpcode(POC_DECFSZ,  pctemp);
10220   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10221   pic16_emitpLabel(tlbl1->key);
10222
10223   pic16_popReleaseTempReg(pctemp,1);
10224
10225
10226  release:
10227   pic16_freeAsmop (right,NULL,ic,TRUE);
10228   pic16_freeAsmop(left,NULL,ic,TRUE);
10229   pic16_freeAsmop(result,NULL,ic,TRUE);
10230 }
10231 #endif
10232
10233 /*-----------------------------------------------------------------*/
10234 /* genrshOne - right shift a one byte quantity by known count      */
10235 /*-----------------------------------------------------------------*/
10236 static void genrshOne (operand *result, operand *left,
10237                        int shCount, int sign)
10238 {
10239     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10240     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10241 }
10242
10243 /*-----------------------------------------------------------------*/
10244 /* genrshTwo - right shift two bytes by known amount != 0          */
10245 /*-----------------------------------------------------------------*/
10246 static void genrshTwo (operand *result,operand *left,
10247                        int shCount, int sign)
10248 {
10249   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10250   /* if shCount >= 8 */
10251   if (shCount >= 8) {
10252     shCount -= 8 ;
10253     if (shCount)
10254       shiftR1Left2Result(left, MSB16, result, LSB,
10255                          shCount, sign);
10256     else
10257       movLeft2Result(left, MSB16, result, LSB);
10258
10259     pic16_addSign (result, 1, sign);
10260   }
10261
10262   /*  1 <= shCount <= 7 */
10263   else
10264     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
10265 }
10266
10267 /*-----------------------------------------------------------------*/
10268 /* shiftRLong - shift right one long from left to result           */
10269 /* offl = LSB or MSB16                                             */
10270 /*-----------------------------------------------------------------*/
10271 static void shiftRLong (operand *left, int offl,
10272                         operand *result, int sign)
10273 {
10274     int size = AOP_SIZE(result);
10275     int same = pic16_sameRegs(AOP(left),AOP(result));
10276     int i;
10277     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10278
10279         if (same && (offl == MSB16)) { //shift one byte right
10280                 for(i=MSB16;i<size;i++) {
10281                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10282                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10283                 }
10284         }
10285
10286     if(sign)
10287                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10288         else
10289                 emitCLRC;
10290
10291         if (same) {
10292                 if (offl == LSB)
10293                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10294         } else {
10295         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10296         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10297         }
10298
10299     if(offl == MSB16) {
10300         /* add sign of "a" */
10301         pic16_addSign(result, MSB32, sign);
10302         }
10303
10304         if (same) {
10305         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10306         } else {
10307         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10308         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10309         }
10310
10311         if (same) {
10312         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10313         } else {
10314         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10315         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10316         }
10317
10318         if (same) {
10319         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10320         } else {
10321         if(offl == LSB){
10322                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10323                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10324         }
10325         }
10326 }
10327
10328 /*-----------------------------------------------------------------*/
10329 /* genrshFour - shift four byte by a known amount != 0             */
10330 /*-----------------------------------------------------------------*/
10331 static void genrshFour (operand *result, operand *left,
10332                         int shCount, int sign)
10333 {
10334   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10335   /* if shifting more that 3 bytes */
10336   if(shCount >= 24 ) {
10337     shCount -= 24;
10338     if(shCount)
10339       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10340     else
10341       movLeft2Result(left, MSB32, result, LSB);
10342
10343     pic16_addSign(result, MSB16, sign);
10344   }
10345   else if(shCount >= 16){
10346     shCount -= 16;
10347     if(shCount)
10348       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10349     else{
10350       movLeft2Result(left, MSB24, result, LSB);
10351       movLeft2Result(left, MSB32, result, MSB16);
10352     }
10353     pic16_addSign(result, MSB24, sign);
10354   }
10355   else if(shCount >= 8){
10356     shCount -= 8;
10357     if(shCount == 1)
10358       shiftRLong(left, MSB16, result, sign);
10359     else if(shCount == 0){
10360       movLeft2Result(left, MSB16, result, LSB);
10361       movLeft2Result(left, MSB24, result, MSB16);
10362       movLeft2Result(left, MSB32, result, MSB24);
10363       pic16_addSign(result, MSB32, sign);
10364     }
10365     else{ //shcount >= 2
10366       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10367       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10368       /* the last shift is signed */
10369       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10370       pic16_addSign(result, MSB32, sign);
10371     }
10372   }
10373   else{   /* 1 <= shCount <= 7 */
10374     if(shCount <= 2){
10375       shiftRLong(left, LSB, result, sign);
10376       if(shCount == 2)
10377         shiftRLong(result, LSB, result, sign);
10378     }
10379     else{
10380       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10381       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10382       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10383     }
10384   }
10385 }
10386
10387 /*-----------------------------------------------------------------*/
10388 /* genRightShiftLiteral - right shifting by known count            */
10389 /*-----------------------------------------------------------------*/
10390 static void genRightShiftLiteral (operand *left,
10391                                   operand *right,
10392                                   operand *result,
10393                                   iCode *ic,
10394                                   int sign)
10395 {
10396   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
10397   int lsize,res_size;
10398
10399   pic16_freeAsmop(right,NULL,ic,TRUE);
10400
10401   pic16_aopOp(left,ic,FALSE);
10402   pic16_aopOp(result,ic,TRUE);
10403
10404   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10405
10406 #if VIEW_SIZE
10407   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10408                  AOP_SIZE(left));
10409 #endif
10410
10411   lsize = pic16_getDataSize(left);
10412   res_size = pic16_getDataSize(result);
10413   /* test the LEFT size !!! */
10414
10415   /* I suppose that the left size >= result size */
10416   if(shCount == 0){
10417     assert (res_size <= lsize);
10418     while (res_size--) {
10419       pic16_mov2f (AOP(result), AOP(left), res_size);
10420     } // for
10421   }
10422
10423   else if(shCount >= (lsize * 8)){
10424
10425     if(res_size == 1) {
10426       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10427       if(sign) {
10428         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10429         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10430       }
10431     } else {
10432
10433       if(sign) {
10434         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10435         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10436         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10437         while(res_size--)
10438           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10439
10440       } else {
10441
10442         while(res_size--)
10443           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10444       }
10445     }
10446   } else {
10447
10448     switch (res_size) {
10449     case 1:
10450       genrshOne (result,left,shCount,sign);
10451       break;
10452
10453     case 2:
10454       genrshTwo (result,left,shCount,sign);
10455       break;
10456
10457     case 4:
10458       genrshFour (result,left,shCount,sign);
10459       break;
10460     default :
10461       break;
10462     }
10463
10464   }
10465
10466   pic16_freeAsmop(left,NULL,ic,TRUE);
10467   pic16_freeAsmop(result,NULL,ic,TRUE);
10468 }
10469
10470 #if !(USE_GENERIC_SIGNED_SHIFT)
10471 /*-----------------------------------------------------------------*/
10472 /* genSignedRightShift - right shift of signed number              */
10473 /*-----------------------------------------------------------------*/
10474 static void genSignedRightShift (iCode *ic)
10475 {
10476   operand *right, *left, *result;
10477   int size, offset;
10478   //  char *l;
10479   symbol *tlbl, *tlbl1 ;
10480   pCodeOp *pctemp;
10481
10482   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10483
10484   /* we do it the hard way put the shift count in b
10485      and loop thru preserving the sign */
10486   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10487
10488   right = IC_RIGHT(ic);
10489   left  = IC_LEFT(ic);
10490   result = IC_RESULT(ic);
10491
10492   pic16_aopOp(right,ic,FALSE);
10493   pic16_aopOp(left,ic,FALSE);
10494   pic16_aopOp(result,ic,FALSE);
10495
10496
10497   if ( AOP_TYPE(right) == AOP_LIT) {
10498     genRightShiftLiteral (left,right,result,ic,1);
10499     return ;
10500   }
10501   /* shift count is unknown then we have to form
10502      a loop get the loop count in B : Note: we take
10503      only the lower order byte since shifting
10504      more that 32 bits make no sense anyway, ( the
10505      largest size of an object can be only 32 bits ) */
10506
10507   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10508   //pic16_emitcode("inc","b");
10509   //pic16_freeAsmop (right,NULL,ic,TRUE);
10510   //pic16_aopOp(left,ic,FALSE);
10511   //pic16_aopOp(result,ic,FALSE);
10512
10513   /* now move the left to the result if they are not the
10514      same */
10515   if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10516       AOP_SIZE(result) > 1) {
10517
10518     size = AOP_SIZE(result);
10519     offset=0;
10520     while (size--) {
10521       /*
10522         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10523         if (*l == '@' && IS_AOP_PREG(result)) {
10524
10525         pic16_emitcode("mov","a,%s",l);
10526         pic16_aopPut(AOP(result),"a",offset);
10527         } else
10528         pic16_aopPut(AOP(result),l,offset);
10529       */
10530       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10531       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10532
10533       offset++;
10534     }
10535   }
10536
10537   /* mov the highest order bit to OVR */
10538   tlbl = newiTempLabel(NULL);
10539   tlbl1= newiTempLabel(NULL);
10540
10541   size = AOP_SIZE(result);
10542   offset = size - 1;
10543
10544   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10545
10546   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10547
10548   /* offset should be 0, 1 or 3 */
10549   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10550   emitSKPNZ;
10551   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10552
10553   pic16_emitpcode(POC_MOVWF, pctemp);
10554
10555
10556   pic16_emitpLabel(tlbl->key);
10557
10558   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10559   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10560
10561   while(--size) {
10562     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10563   }
10564
10565   pic16_emitpcode(POC_DECFSZ,  pctemp);
10566   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10567   pic16_emitpLabel(tlbl1->key);
10568
10569   pic16_popReleaseTempReg(pctemp,1);
10570 #if 0
10571   size = AOP_SIZE(result);
10572   offset = size - 1;
10573   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10574   pic16_emitcode("rlc","a");
10575   pic16_emitcode("mov","ov,c");
10576   /* if it is only one byte then */
10577   if (size == 1) {
10578     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10579     MOVA(l);
10580     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10581     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10582     pic16_emitcode("mov","c,ov");
10583     pic16_emitcode("rrc","a");
10584     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10585     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10586     pic16_aopPut(AOP(result),"a",0);
10587     goto release ;
10588   }
10589
10590   reAdjustPreg(AOP(result));
10591   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10592   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10593   pic16_emitcode("mov","c,ov");
10594   while (size--) {
10595     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10596     MOVA(l);
10597     pic16_emitcode("rrc","a");
10598     pic16_aopPut(AOP(result),"a",offset--);
10599   }
10600   reAdjustPreg(AOP(result));
10601   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10602   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10603
10604  release:
10605 #endif
10606
10607   pic16_freeAsmop(left,NULL,ic,TRUE);
10608   pic16_freeAsmop(result,NULL,ic,TRUE);
10609   pic16_freeAsmop(right,NULL,ic,TRUE);
10610 }
10611 #endif
10612
10613 #if !(USE_GENERIC_SIGNED_SHIFT)
10614 #warning This implementation of genRightShift() is incomplete!
10615 /*-----------------------------------------------------------------*/
10616 /* genRightShift - generate code for right shifting                */
10617 /*-----------------------------------------------------------------*/
10618 static void genRightShift (iCode *ic)
10619 {
10620     operand *right, *left, *result;
10621     sym_link *letype ;
10622     int size, offset;
10623     char *l;
10624     symbol *tlbl, *tlbl1 ;
10625
10626     /* if signed then we do it the hard way preserve the
10627     sign bit moving it inwards */
10628     letype = getSpec(operandType(IC_LEFT(ic)));
10629     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10630
10631     if (!SPEC_USIGN(letype)) {
10632         genSignedRightShift (ic);
10633         return ;
10634     }
10635
10636     /* signed & unsigned types are treated the same : i.e. the
10637     signed is NOT propagated inwards : quoting from the
10638     ANSI - standard : "for E1 >> E2, is equivalent to division
10639     by 2**E2 if unsigned or if it has a non-negative value,
10640     otherwise the result is implementation defined ", MY definition
10641     is that the sign does not get propagated */
10642
10643     right = IC_RIGHT(ic);
10644     left  = IC_LEFT(ic);
10645     result = IC_RESULT(ic);
10646
10647     pic16_aopOp(right,ic,FALSE);
10648
10649     /* if the shift count is known then do it
10650     as efficiently as possible */
10651     if (AOP_TYPE(right) == AOP_LIT) {
10652         genRightShiftLiteral (left,right,result,ic, 0);
10653         return ;
10654     }
10655
10656     /* shift count is unknown then we have to form
10657     a loop get the loop count in B : Note: we take
10658     only the lower order byte since shifting
10659     more that 32 bits make no sense anyway, ( the
10660     largest size of an object can be only 32 bits ) */
10661
10662     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10663     pic16_emitcode("inc","b");
10664     pic16_aopOp(left,ic,FALSE);
10665     pic16_aopOp(result,ic,FALSE);
10666
10667     /* now move the left to the result if they are not the
10668     same */
10669     if (!pic16_sameRegs(AOP(left),AOP(result)) &&
10670         AOP_SIZE(result) > 1) {
10671
10672         size = AOP_SIZE(result);
10673         offset=0;
10674         while (size--) {
10675             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10676             if (*l == '@' && IS_AOP_PREG(result)) {
10677
10678                 pic16_emitcode("mov","a,%s",l);
10679                 pic16_aopPut(AOP(result),"a",offset);
10680             } else
10681                 pic16_aopPut(AOP(result),l,offset);
10682             offset++;
10683         }
10684     }
10685
10686     tlbl = newiTempLabel(NULL);
10687     tlbl1= newiTempLabel(NULL);
10688     size = AOP_SIZE(result);
10689     offset = size - 1;
10690
10691     /* if it is only one byte then */
10692     if (size == 1) {
10693
10694       tlbl = newiTempLabel(NULL);
10695       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10696         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10697         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10698       }
10699
10700       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10701       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10702       pic16_emitpLabel(tlbl->key);
10703       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10704       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10705       emitSKPC;
10706       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10707
10708       goto release ;
10709     }
10710
10711     reAdjustPreg(AOP(result));
10712     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10713     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10714     CLRC;
10715     while (size--) {
10716         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10717         MOVA(l);
10718         pic16_emitcode("rrc","a");
10719         pic16_aopPut(AOP(result),"a",offset--);
10720     }
10721     reAdjustPreg(AOP(result));
10722
10723     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10724     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10725
10726 release:
10727     pic16_freeAsmop(left,NULL,ic,TRUE);
10728     pic16_freeAsmop (right,NULL,ic,TRUE);
10729     pic16_freeAsmop(result,NULL,ic,TRUE);
10730 }
10731 #endif
10732
10733 #if (USE_GENERIC_SIGNED_SHIFT)
10734 /*-----------------------------------------------------------------*/
10735 /* genGenericShift - generates code for left or right shifting     */
10736 /*-----------------------------------------------------------------*/
10737 static void genGenericShift (iCode *ic, int isShiftLeft) {
10738   operand *left,*right, *result;
10739   int offset;
10740   int sign, signedCount;
10741   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10742   PIC_OPCODE pos_shift, neg_shift;
10743
10744   FENTRY;
10745
10746   right = IC_RIGHT(ic);
10747   left  = IC_LEFT(ic);
10748   result = IC_RESULT(ic);
10749
10750   pic16_aopOp(right,ic,FALSE);
10751   pic16_aopOp(left,ic,FALSE);
10752   pic16_aopOp(result,ic,TRUE);
10753
10754   sign = !SPEC_USIGN(operandType (left));
10755   signedCount = !SPEC_USIGN(operandType (right));
10756
10757   /* if the shift count is known then do it
10758      as efficiently as possible */
10759   if (AOP_TYPE(right) == AOP_LIT) {
10760     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
10761     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10762     // we should modify right->aopu.aop_lit here!
10763     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10764     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10765     if (isShiftLeft)
10766       pic16_genLeftShiftLiteral (left,right,result,ic);
10767     else
10768       genRightShiftLiteral (left,right,result,ic, sign);
10769
10770     goto release;
10771   } // if (right is literal)
10772
10773   /* shift count is unknown then we have to form a loop.
10774    * Note: we take only the lower order byte since shifting
10775    * more than 32 bits make no sense anyway, ( the
10776    * largest size of an object can be only 32 bits )
10777    * Note: we perform arithmetic shifts if the left operand is
10778    * signed and we do an (effective) right shift, i. e. we
10779    * shift in the sign bit from the left. */
10780
10781   label_complete = newiTempLabel ( NULL );
10782   label_loop_pos = newiTempLabel ( NULL );
10783   label_loop_neg = NULL;
10784   label_negative = NULL;
10785   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10786   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10787
10788   if (signedCount) {
10789     // additional labels needed
10790     label_loop_neg = newiTempLabel ( NULL );
10791     label_negative = newiTempLabel ( NULL );
10792   } // if
10793
10794   // copy source to result -- this will effectively truncate the left operand to the size of result!
10795   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10796   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10797   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10798     pic16_mov2f (AOP(result),AOP(left), offset);
10799   } // for
10800
10801   // if result is longer than left, fill with zeros (or sign)
10802   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10803     if (sign && AOP_SIZE(left) > 0) {
10804       // shift signed operand -- fill with sign
10805       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10806       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10807       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10808       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10809         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10810       } // for
10811     } else {
10812       // shift unsigned operand -- fill result with zeros
10813       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10814         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10815       } // for
10816     }
10817   } // if (size mismatch)
10818
10819   pic16_mov2w (AOP(right), 0);
10820   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10821   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10822
10823 #if 0
10824   // perform a shift by one (shift count is positive)
10825   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10826   // 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])
10827   pic16_emitpLabel (label_loop_pos->key);
10828   emitCLRC;
10829   if (sign && (pos_shift == POC_RRCF)) {
10830     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10831     emitSETC;
10832   } // if
10833   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10834   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10835   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10836 #else
10837   // perform a shift by one (shift count is positive)
10838   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10839   // 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])
10840   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10841   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10842   emitCLRC;
10843   pic16_emitpLabel (label_loop_pos->key);
10844   if (sign && (pos_shift == POC_RRCF)) {
10845     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10846     emitSETC;
10847   } // if
10848   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10849   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10850   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10851   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10852 #endif
10853
10854   if (signedCount) {
10855     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10856
10857     pic16_emitpLabel (label_negative->key);
10858     // perform a shift by -1 (shift count is negative)
10859     // 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)
10860     emitCLRC;
10861     pic16_emitpLabel (label_loop_neg->key);
10862     if (sign && (neg_shift == POC_RRCF)) {
10863       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10864       emitSETC;
10865     } // if
10866     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10867     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10868     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10869     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10870   } // if (signedCount)
10871
10872   pic16_emitpLabel (label_complete->key);
10873
10874 release:
10875   pic16_freeAsmop (right,NULL,ic,TRUE);
10876   pic16_freeAsmop(left,NULL,ic,TRUE);
10877   pic16_freeAsmop(result,NULL,ic,TRUE);
10878 }
10879
10880 static void genLeftShift (iCode *ic) {
10881   genGenericShift (ic, 1);
10882 }
10883
10884 static void genRightShift (iCode *ic) {
10885   genGenericShift (ic, 0);
10886 }
10887 #endif
10888
10889
10890 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10891 void pic16_loadFSR0(operand *op, int lit)
10892 {
10893   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10894     if (AOP_TYPE(op) == AOP_LIT) {
10895       /* handle 12 bit integers correctly */
10896       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
10897       if ((val & 0x0fff) != val) {
10898         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10899                 val, (val & 0x0fff) );
10900         val &= 0x0fff;
10901       }
10902       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10903     } else {
10904       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10905     }
10906   } else {
10907     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10908     // set up FSR0 with address of result
10909     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10910     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10911   }
10912 }
10913
10914 /*----------------------------------------------------------------*/
10915 /* pic16_derefPtr - move one byte from the location ptr points to */
10916 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10917 /*                  to the location ptr points to (doWrite != 0)   */
10918 /*----------------------------------------------------------------*/
10919 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10920 {
10921   if (!IS_PTR(operandType(ptr)))
10922   {
10923     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10924     else pic16_mov2w (AOP(ptr), 0);
10925     return;
10926   }
10927
10928   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10929   /* We might determine pointer type right here: */
10930   p_type = DCL_TYPE(operandType(ptr));
10931
10932   switch (p_type) {
10933     case FPOINTER:
10934     case POINTER:
10935       if (!fsr0_setup || !*fsr0_setup)
10936       {
10937         pic16_loadFSR0( ptr, 0 );
10938         if (fsr0_setup) *fsr0_setup = 1;
10939       }
10940       if (doWrite)
10941         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10942       else
10943         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10944       break;
10945
10946     case GPOINTER:
10947       if (AOP(ptr)->aopu.aop_reg[2]) {
10948         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10949         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10950         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10951         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10952         pic16_mov2w(AOP(ptr), 2);
10953         pic16_callGenericPointerRW(doWrite, 1);
10954       } else {
10955         // data pointer (just 2 byte given)
10956         if (!fsr0_setup || !*fsr0_setup)
10957         {
10958           pic16_loadFSR0( ptr, 0 );
10959           if (fsr0_setup) *fsr0_setup = 1;
10960         }
10961         if (doWrite)
10962           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10963         else
10964           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10965       }
10966       break;
10967
10968     default:
10969       assert (0 && "invalid pointer type specified");
10970       break;
10971   }
10972 }
10973
10974 /*-----------------------------------------------------------------*/
10975 /* genUnpackBits - generates code for unpacking bits               */
10976 /*-----------------------------------------------------------------*/
10977 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10978 {
10979   int shCnt ;
10980   sym_link *etype, *letype;
10981   int blen=0, bstr=0;
10982   int lbstr;
10983   int same;
10984   pCodeOp *op;
10985
10986   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10987   etype = getSpec(operandType(result));
10988   letype = getSpec(operandType(left));
10989
10990   //    if(IS_BITFIELD(etype)) {
10991   blen = SPEC_BLEN(etype);
10992   bstr = SPEC_BSTR(etype);
10993   //    }
10994
10995   lbstr = SPEC_BSTR( letype );
10996
10997   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10998       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10999
11000 #if 1
11001   if((blen == 1) && (bstr < 8)
11002       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
11003     /* it is a single bit, so use the appropriate bit instructions */
11004     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
11005
11006     same = pic16_sameRegs(AOP(left),AOP(result));
11007     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
11008     pic16_emitpcode(POC_CLRF, op);
11009
11010     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
11011       /* workaround to reduce the extra lfsr instruction */
11012       pic16_emitpcode(POC_BTFSC,
11013           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
11014     } else {
11015       assert (PIC_IS_DATA_PTR (operandType(left)));
11016       pic16_loadFSR0 (left, 0);
11017       pic16_emitpcode(POC_BTFSC,
11018           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11019     }
11020
11021     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
11022       /* unsigned bitfields result in either 0 or 1 */
11023       pic16_emitpcode(POC_INCF, op);
11024     } else {
11025       /* signed bitfields result in either 0 or -1 */
11026       pic16_emitpcode(POC_DECF, op);
11027     }
11028     if (same) {
11029       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
11030     }
11031
11032     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
11033     return;
11034   }
11035
11036 #endif
11037
11038   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
11039     // access symbol directly
11040     pic16_mov2w (AOP(left), 0);
11041   } else {
11042     pic16_derefPtr (left, ptype, 0, NULL);
11043   }
11044
11045   /* if we have bitdisplacement then it fits   */
11046   /* into this byte completely or if length is */
11047   /* less than a byte                          */
11048   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
11049
11050     /* shift right acc */
11051     AccRsh(shCnt, 0);
11052
11053     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11054           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
11055
11056     /* VR -- normally I would use the following, but since we use the hack,
11057      * to avoid the masking from AccRsh, why not mask it right now? */
11058
11059     /*
11060        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
11061      */
11062
11063     /* extend signed bitfields to 8 bits */
11064     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
11065     {
11066       assert (blen + bstr > 0);
11067       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
11068       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
11069     }
11070
11071     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11072
11073     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
11074     return ;
11075   }
11076
11077   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
11078   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11079   exit(EXIT_FAILURE);
11080
11081   return ;
11082 }
11083
11084
11085 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
11086 {
11087   int size, offset = 0, leoffset=0 ;
11088
11089         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11090         pic16_aopOp(result, ic, TRUE);
11091
11092         FENTRY;
11093
11094         size = AOP_SIZE(result);
11095 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11096
11097
11098 #if 1
11099         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
11100                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
11101                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11102                 goto release;
11103         }
11104 #endif
11105
11106         if(AOP(left)->aopu.pcop->type == PO_DIR)
11107                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11108
11109         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11110
11111         while (size--) {
11112                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11113
11114 //              pic16_DumpOp("(result)",result);
11115                 if(is_LitAOp(AOP(result))) {
11116                         pic16_mov2w(AOP(left), offset); // patch 8
11117                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11118                 } else {
11119                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11120                                 pic16_popGet(AOP(left), offset), //patch 8
11121                                 pic16_popGet(AOP(result), offset)));
11122                 }
11123
11124                 offset++;
11125                 leoffset++;
11126         }
11127
11128 release:
11129     pic16_freeAsmop(result,NULL,ic,TRUE);
11130 }
11131
11132
11133
11134 /*-----------------------------------------------------------------*/
11135 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11136 /*-----------------------------------------------------------------*/
11137 static void genNearPointerGet (operand *left,
11138                                operand *result,
11139                                iCode *ic)
11140 {
11141 //  asmop *aop = NULL;
11142   //regs *preg = NULL ;
11143   sym_link *rtype, *retype;
11144   sym_link *ltype, *letype;
11145
11146     FENTRY;
11147
11148     rtype = operandType(result);
11149     retype= getSpec(rtype);
11150     ltype = operandType(left);
11151     letype= getSpec(ltype);
11152
11153     pic16_aopOp(left,ic,FALSE);
11154
11155 //    pic16_DumpOp("(left)",left);
11156 //    pic16_DumpOp("(result)",result);
11157
11158     /* if left is rematerialisable and
11159      * result is not bit variable type and
11160      * the left is pointer to data space i.e
11161      * lower 128 bytes of space */
11162
11163     if (AOP_TYPE(left) == AOP_PCODE
11164       && !IS_BITFIELD(retype)
11165       && DCL_TYPE(ltype) == POINTER) {
11166
11167         genDataPointerGet (left,result,ic);
11168         pic16_freeAsmop(left, NULL, ic, TRUE);
11169         return ;
11170     }
11171
11172     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11173     pic16_aopOp (result,ic,TRUE);
11174
11175     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11176
11177 #if 1
11178     if(IS_BITFIELD( retype )
11179       && (SPEC_BLEN(operandType(result))==1)
11180     ) {
11181       iCode *nextic;
11182       pCodeOp *jop;
11183       int bitstrt, bytestrt;
11184
11185         /* if this is bitfield of size 1, see if we are checking the value
11186          * of a single bit in an if-statement,
11187          * if yes, then don't generate usual code, but execute the
11188          * genIfx directly -- VR */
11189
11190         nextic = ic->next;
11191
11192         /* CHECK: if next iCode is IFX
11193          * and current result operand is nextic's conditional operand
11194          * and current result operand live ranges ends at nextic's key number
11195          */
11196         if((nextic->op == IFX)
11197           && (result == IC_COND(nextic))
11198           && (OP_LIVETO(result) == nextic->seq)
11199           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11200           ) {
11201             /* everything is ok then */
11202             /* find a way to optimize the genIfx iCode */
11203
11204             bytestrt = SPEC_BSTR(operandType(result))/8;
11205             bitstrt = SPEC_BSTR(operandType(result))%8;
11206
11207             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11208
11209             genIfxpCOpJump(nextic, jop);
11210
11211             pic16_freeAsmop(left, NULL, ic, TRUE);
11212             pic16_freeAsmop(result, NULL, ic, TRUE);
11213             return;
11214         }
11215     }
11216 #endif
11217
11218     /* if bitfield then unpack the bits */
11219     if (IS_BITFIELD(letype))
11220       genUnpackBits (result, left, NULL, POINTER);
11221     else {
11222       /* we have can just get the values */
11223       int size = AOP_SIZE(result);
11224       int offset = 0;
11225
11226       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11227
11228       pic16_loadFSR0( left, 0 );
11229
11230       while(size--) {
11231         if(size) {
11232           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11233                 pic16_popGet(AOP(result), offset++)));
11234         } else {
11235           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11236                 pic16_popGet(AOP(result), offset++)));
11237         }
11238       }
11239     }
11240
11241 #if 0
11242     /* now some housekeeping stuff */
11243     if (aop) {
11244       /* we had to allocate for this iCode */
11245       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11246       pic16_freeAsmop(NULL,aop,ic,TRUE);
11247     } else {
11248       /* we did not allocate which means left
11249        * already in a pointer register, then
11250        * if size > 0 && this could be used again
11251        * we have to point it back to where it
11252        * belongs */
11253       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11254       if (AOP_SIZE(result) > 1
11255         && !OP_SYMBOL(left)->remat
11256         && ( OP_SYMBOL(left)->liveTo > ic->seq
11257             || ic->depth )) {
11258 //        int size = AOP_SIZE(result) - 1;
11259 //        while (size--)
11260 //          pic16_emitcode("dec","%s",rname);
11261         }
11262     }
11263 #endif
11264
11265     /* done */
11266     pic16_freeAsmop(left,NULL,ic,TRUE);
11267     pic16_freeAsmop(result,NULL,ic,TRUE);
11268 }
11269
11270 /*-----------------------------------------------------------------*/
11271 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11272 /*-----------------------------------------------------------------*/
11273 static void genPagedPointerGet (operand *left,
11274                                operand *result,
11275                                iCode *ic)
11276 {
11277     asmop *aop = NULL;
11278     regs *preg = NULL ;
11279     char *rname ;
11280     sym_link *rtype, *retype;
11281
11282     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11283
11284     rtype = operandType(result);
11285     retype= getSpec(rtype);
11286
11287     pic16_aopOp(left,ic,FALSE);
11288
11289   /* if the value is already in a pointer register
11290        then don't need anything more */
11291     if (!AOP_INPREG(AOP(left))) {
11292         /* otherwise get a free pointer register */
11293         aop = newAsmop(0);
11294         preg = getFreePtr(ic,&aop,FALSE);
11295         pic16_emitcode("mov","%s,%s",
11296                 preg->name,
11297                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11298         rname = preg->name ;
11299     } else
11300         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11301
11302     pic16_freeAsmop(left,NULL,ic,TRUE);
11303     pic16_aopOp (result,ic,TRUE);
11304
11305     /* if bitfield then unpack the bits */
11306     if (IS_BITFIELD(retype))
11307         genUnpackBits (result,left,rname,PPOINTER);
11308     else {
11309         /* we have can just get the values */
11310         int size = AOP_SIZE(result);
11311         int offset = 0 ;
11312
11313         while (size--) {
11314
11315             pic16_emitcode("movx","a,@%s",rname);
11316             pic16_aopPut(AOP(result),"a",offset);
11317
11318             offset++ ;
11319
11320             if (size)
11321                 pic16_emitcode("inc","%s",rname);
11322         }
11323     }
11324
11325     /* now some housekeeping stuff */
11326     if (aop) {
11327         /* we had to allocate for this iCode */
11328         pic16_freeAsmop(NULL,aop,ic,TRUE);
11329     } else {
11330         /* we did not allocate which means left
11331            already in a pointer register, then
11332            if size > 0 && this could be used again
11333            we have to point it back to where it
11334            belongs */
11335         if (AOP_SIZE(result) > 1 &&
11336             !OP_SYMBOL(left)->remat &&
11337             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11338               ic->depth )) {
11339             int size = AOP_SIZE(result) - 1;
11340             while (size--)
11341                 pic16_emitcode("dec","%s",rname);
11342         }
11343     }
11344
11345     /* done */
11346     pic16_freeAsmop(result,NULL,ic,TRUE);
11347
11348
11349 }
11350
11351 #if 0
11352 /* This code is not adjusted to PIC16 and fails utterly.
11353  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11354
11355 /*-----------------------------------------------------------------*/
11356 /* genFarPointerGet - gget value from far space                    */
11357 /*-----------------------------------------------------------------*/
11358 static void genFarPointerGet (operand *left,
11359                               operand *result, iCode *ic)
11360 {
11361     int size, offset ;
11362     sym_link *retype = getSpec(operandType(result));
11363
11364     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11365
11366     pic16_aopOp(left,ic,FALSE);
11367
11368     /* if the operand is already in dptr
11369     then we do nothing else we move the value to dptr */
11370     if (AOP_TYPE(left) != AOP_STR) {
11371         /* if this is remateriazable */
11372         if (AOP_TYPE(left) == AOP_IMMD)
11373             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11374         else { /* we need to get it byte by byte */
11375             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11376             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11377             if (options.model == MODEL_FLAT24)
11378             {
11379                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11380             }
11381         }
11382     }
11383     /* so dptr know contains the address */
11384     pic16_freeAsmop(left,NULL,ic,TRUE);
11385     pic16_aopOp(result,ic,TRUE);
11386
11387     /* if bit then unpack */
11388     if (IS_BITFIELD(retype))
11389         genUnpackBits(result,left,"dptr",FPOINTER);
11390     else {
11391         size = AOP_SIZE(result);
11392         offset = 0 ;
11393
11394         while (size--) {
11395             pic16_emitcode("movx","a,@dptr");
11396             pic16_aopPut(AOP(result),"a",offset++);
11397             if (size)
11398                 pic16_emitcode("inc","dptr");
11399         }
11400     }
11401
11402     pic16_freeAsmop(result,NULL,ic,TRUE);
11403 }
11404 #endif
11405
11406 #if 0
11407 /*-----------------------------------------------------------------*/
11408 /* genCodePointerGet - get value from code space                  */
11409 /*-----------------------------------------------------------------*/
11410 static void genCodePointerGet (operand *left,
11411                                 operand *result, iCode *ic)
11412 {
11413     int size, offset ;
11414     sym_link *retype = getSpec(operandType(result));
11415
11416     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11417
11418     pic16_aopOp(left,ic,FALSE);
11419
11420     /* if the operand is already in dptr
11421     then we do nothing else we move the value to dptr */
11422     if (AOP_TYPE(left) != AOP_STR) {
11423         /* if this is remateriazable */
11424         if (AOP_TYPE(left) == AOP_IMMD)
11425             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11426         else { /* we need to get it byte by byte */
11427             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11428             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11429             if (options.model == MODEL_FLAT24)
11430             {
11431                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11432             }
11433         }
11434     }
11435     /* so dptr know contains the address */
11436     pic16_freeAsmop(left,NULL,ic,TRUE);
11437     pic16_aopOp(result,ic,FALSE);
11438
11439     /* if bit then unpack */
11440     if (IS_BITFIELD(retype))
11441         genUnpackBits(result,left,"dptr",CPOINTER);
11442     else {
11443         size = AOP_SIZE(result);
11444         offset = 0 ;
11445
11446         while (size--) {
11447             pic16_emitcode("clr","a");
11448             pic16_emitcode("movc","a,@a+dptr");
11449             pic16_aopPut(AOP(result),"a",offset++);
11450             if (size)
11451                 pic16_emitcode("inc","dptr");
11452         }
11453     }
11454
11455     pic16_freeAsmop(result,NULL,ic,TRUE);
11456 }
11457 #endif
11458
11459 #if 0
11460 /*-----------------------------------------------------------------*/
11461 /* genGenPointerGet - gget value from generic pointer space        */
11462 /*-----------------------------------------------------------------*/
11463 static void genGenPointerGet (operand *left,
11464                               operand *result, iCode *ic)
11465 {
11466   int size, offset, lit;
11467   sym_link *retype = getSpec(operandType(result));
11468
11469         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11470         pic16_aopOp(left,ic,FALSE);
11471         pic16_aopOp(result,ic,FALSE);
11472         size = AOP_SIZE(result);
11473
11474         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11475
11476         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11477
11478                 lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11479                 // load FSR0 from immediate
11480                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11481
11482 //              pic16_loadFSR0( left );
11483
11484                 offset = 0;
11485                 while(size--) {
11486                         if(size) {
11487                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11488                         } else {
11489                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11490                         }
11491                         offset++;
11492                 }
11493                 goto release;
11494
11495         }
11496         else { /* we need to get it byte by byte */
11497                 // set up FSR0 with address from left
11498                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11499                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11500
11501                 offset = 0 ;
11502
11503                 while(size--) {
11504                         if(size) {
11505                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11506                         } else {
11507                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11508                         }
11509                         offset++;
11510                 }
11511                 goto release;
11512         }
11513
11514   /* if bit then unpack */
11515         if (IS_BITFIELD(retype))
11516                 genUnpackBits(result,left,"BAD",GPOINTER);
11517
11518         release:
11519         pic16_freeAsmop(left,NULL,ic,TRUE);
11520         pic16_freeAsmop(result,NULL,ic,TRUE);
11521
11522 }
11523 #endif
11524
11525
11526 /*-----------------------------------------------------------------*/
11527 /* genGenPointerGet - gget value from generic pointer space        */
11528 /*-----------------------------------------------------------------*/
11529 static void genGenPointerGet (operand *left,
11530                               operand *result, iCode *ic)
11531 {
11532   int size, offset, lit;
11533   sym_link *letype = getSpec(operandType(left));
11534
11535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11536     pic16_aopOp(left,ic,FALSE);
11537     pic16_aopOp(result,ic,TRUE);
11538     size = AOP_SIZE(result);
11539
11540     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11541
11542     /* if bit then unpack */
11543     if (IS_BITFIELD(letype)) {
11544       genUnpackBits(result,left,"BAD",GPOINTER);
11545       goto release;
11546     }
11547
11548     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11549
11550       lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit);
11551       // load FSR0 from immediate
11552       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11553
11554       werror(W_POSSBUG2, __FILE__, __LINE__);
11555
11556       offset = 0;
11557       while(size--) {
11558         if(size) {
11559           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11560         } else {
11561           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11562         }
11563         offset++;
11564       }
11565
11566       goto release;
11567
11568     } else { /* we need to get it byte by byte */
11569
11570       /* set up WREG:PRODL:FSR0L with address from left */
11571       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11572       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11573       pic16_mov2w(AOP(left), 2);
11574       pic16_callGenericPointerRW(0, size);
11575
11576       assignResultValue(result, size, 1);
11577
11578       goto release;
11579     }
11580
11581 release:
11582   pic16_freeAsmop(left,NULL,ic,TRUE);
11583   pic16_freeAsmop(result,NULL,ic,TRUE);
11584 }
11585
11586 /*-----------------------------------------------------------------*/
11587 /* genConstPointerGet - get value from const generic pointer space */
11588 /*-----------------------------------------------------------------*/
11589 static void genConstPointerGet (operand *left,
11590                                 operand *result, iCode *ic)
11591 {
11592   //sym_link *retype = getSpec(operandType(result));
11593   // symbol *albl = newiTempLabel(NULL);        // patch 15
11594   // symbol *blbl = newiTempLabel(NULL);        //
11595   // PIC_OPCODE poc;                            // patch 15
11596   int size;
11597   int offset = 0;
11598
11599   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11600   pic16_aopOp(left,ic,FALSE);
11601   pic16_aopOp(result,ic,TRUE);
11602   size = AOP_SIZE(result);
11603
11604   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11605
11606   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11607
11608   // set up table pointer
11609   if( (AOP_TYPE(left) == AOP_PCODE)
11610       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11611           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11612     {
11613       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11614       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11615       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11616       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11617       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11618       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11619   } else {
11620     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11621     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11622     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11623   }
11624
11625   while(size--) {
11626     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11627     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11628     offset++;
11629   }
11630
11631   pic16_freeAsmop(left,NULL,ic,TRUE);
11632   pic16_freeAsmop(result,NULL,ic,TRUE);
11633 }
11634
11635
11636 /*-----------------------------------------------------------------*/
11637 /* genPointerGet - generate code for pointer get                   */
11638 /*-----------------------------------------------------------------*/
11639 static void genPointerGet (iCode *ic)
11640 {
11641   operand *left, *result ;
11642   sym_link *type, *etype;
11643   int p_type;
11644
11645     FENTRY;
11646
11647     left = IC_LEFT(ic);
11648     result = IC_RESULT(ic) ;
11649
11650     /* depending on the type of pointer we need to
11651     move it to the correct pointer register */
11652     type = operandType(left);
11653     etype = getSpec(type);
11654
11655 #if 0
11656     if (IS_PTR_CONST(type))
11657 #else
11658     if (IS_CODEPTR(type))
11659 #endif
11660       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11661
11662     /* if left is of type of pointer then it is simple */
11663     if (IS_PTR(type) && !IS_FUNC(type->next))
11664       p_type = DCL_TYPE(type);
11665     else {
11666       /* we have to go by the storage class */
11667       p_type = PTR_TYPE(SPEC_OCLS(etype));
11668
11669       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11670
11671       if (SPEC_OCLS(etype)->codesp ) {
11672         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11673         //p_type = CPOINTER ;
11674       } else
11675       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11676         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11677         /*p_type = FPOINTER ;*/
11678       } else
11679       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11680         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11681         /* p_type = PPOINTER; */
11682       } else
11683       if (SPEC_OCLS(etype) == idata ) {
11684         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11685         /* p_type = IPOINTER; */
11686       } else {
11687         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11688         /* p_type = POINTER ; */
11689       }
11690     }
11691
11692     /* now that we have the pointer type we assign
11693     the pointer values */
11694     switch (p_type) {
11695       case POINTER:
11696       case FPOINTER:
11697       case IPOINTER:
11698         genNearPointerGet (left,result,ic);
11699         break;
11700
11701       case PPOINTER:
11702         genPagedPointerGet(left,result,ic);
11703         break;
11704
11705 #if 0
11706       /* PICs do not support FAR pointers... */
11707       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11708       case FPOINTER:
11709         genFarPointerGet (left,result,ic);
11710         break;
11711 #endif
11712
11713       case CPOINTER:
11714         genConstPointerGet (left,result,ic);
11715         //pic16_emitcodePointerGet (left,result,ic);
11716         break;
11717
11718       case GPOINTER:
11719 #if 0
11720       if (IS_PTR_CONST(type))
11721         genConstPointerGet (left,result,ic);
11722       else
11723 #endif
11724         genGenPointerGet (left,result,ic);
11725       break;
11726
11727     default:
11728       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11729               "genPointerGet: illegal pointer type");
11730
11731     }
11732 }
11733
11734 /*-----------------------------------------------------------------*/
11735 /* genPackBits - generates code for packed bit storage             */
11736 /*-----------------------------------------------------------------*/
11737 static void genPackBits (sym_link    *etype , operand *result,
11738                          operand *right ,
11739                          char *rname, int p_type)
11740 {
11741   int shCnt = 0 ;
11742   int offset = 0  ;
11743   int rLen = 0 ;
11744   int blen, bstr ;
11745   int shifted_and_masked = 0;
11746   unsigned long lit = (unsigned long)-1;
11747   sym_link *retype;
11748
11749   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11750   blen = SPEC_BLEN(etype);
11751   bstr = SPEC_BSTR(etype);
11752
11753   retype = getSpec(operandType(right));
11754
11755   if(AOP_TYPE(right) == AOP_LIT) {
11756     lit = ulFromVal (AOP(right)->aopu.aop_lit);
11757
11758     if((blen == 1) && (bstr < 8)) {
11759       /* it is a single bit, so use the appropriate bit instructions */
11760
11761       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11762
11763       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11764         /* workaround to reduce the extra lfsr instruction */
11765         if(lit) {
11766           pic16_emitpcode(POC_BSF,
11767               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11768         } else {
11769           pic16_emitpcode(POC_BCF,
11770               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11771         }
11772       } else {
11773         if (PIC_IS_DATA_PTR(operandType(result))) {
11774           pic16_loadFSR0(result, 0);
11775           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11776               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11777         } else {
11778           /* get old value */
11779           pic16_derefPtr (result, p_type, 0, NULL);
11780           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11781               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11782           /* write back new value */
11783           pic16_derefPtr (result, p_type, 1, NULL);
11784         }
11785       }
11786
11787       return;
11788     }
11789     /* IORLW below is more efficient */
11790     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11791     lit = (lit & ((1UL << blen) - 1)) << bstr;
11792     shifted_and_masked = 1;
11793     offset++;
11794   } else
11795     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11796         && IS_BITFIELD(retype)
11797         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11798         && (blen == 1)) {
11799       int rblen, rbstr;
11800
11801       rblen = SPEC_BLEN( retype );
11802       rbstr = SPEC_BSTR( retype );
11803
11804       if(IS_BITFIELD(etype)) {
11805         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11806         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11807       } else {
11808         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11809       }
11810
11811       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11812
11813       if(IS_BITFIELD(etype)) {
11814         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11815       } else {
11816         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11817       }
11818
11819       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11820
11821       return;
11822     } else {
11823       /* move right to W */
11824       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11825     }
11826
11827   /* if the bit length is less than or   */
11828   /* it exactly fits a byte then         */
11829   if((shCnt=SPEC_BSTR(etype))
11830       || SPEC_BLEN(etype) <= 8 )  {
11831     int fsr0_setup = 0;
11832
11833     if (blen != 8 || (bstr % 8) != 0) {
11834       // we need to combine the value with the old value
11835       if(!shifted_and_masked)
11836       {
11837         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11838
11839         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11840             SPEC_BSTR(etype), SPEC_BLEN(etype));
11841
11842         /* shift left acc, do NOT mask the result again */
11843         AccLsh(shCnt, 0);
11844
11845         /* using PRODH as a temporary register here */
11846         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11847       }
11848
11849       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11850         || IS_DIRECT(result)) {
11851         /* access symbol directly */
11852         pic16_mov2w (AOP(result), 0);
11853       } else {
11854         /* get old value */
11855         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11856       }
11857 #if 1
11858       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11859             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11860                             (unsigned char)(0xff >> (8-bstr))) ));
11861       if (!shifted_and_masked) {
11862         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11863       } else {
11864         /* We have the shifted and masked (literal) right value in `lit' */
11865         if (lit != 0)
11866           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11867       }
11868     } else { // if (blen == 8 && (bstr % 8) == 0)
11869         if (shifted_and_masked) {
11870             // move right (literal) to WREG (only case where right is not yet in WREG)
11871             pic16_mov2w(AOP(right), (bstr / 8));
11872         }
11873     }
11874
11875     /* write new value back */
11876     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11877         || IS_DIRECT(result)) {
11878       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11879     } else {
11880       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11881     }
11882 #endif
11883
11884     return;
11885   }
11886
11887
11888 #if 0
11889   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11890   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11891   exit(EXIT_FAILURE);
11892 #endif
11893
11894
11895   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11896   rLen = SPEC_BLEN(etype)-8;
11897
11898   /* now generate for lengths greater than one byte */
11899   while (1) {
11900     rLen -= 8 ;
11901     if (rLen <= 0 ) {
11902       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11903       break ;
11904     }
11905
11906     switch (p_type) {
11907       case POINTER:
11908         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11909         break;
11910
11911         /*
11912            case FPOINTER:
11913            MOVA(l);
11914            pic16_emitcode("movx","@dptr,a");
11915            break;
11916
11917            case GPOINTER:
11918            MOVA(l);
11919            DEBUGpic16_emitcode(";lcall","__gptrput");
11920            break;
11921          */
11922       default:
11923         assert(0);
11924     }
11925
11926
11927     pic16_mov2w(AOP(right), offset++);
11928   }
11929
11930   /* last last was not complete */
11931   if (rLen)   {
11932     /* save the byte & read byte */
11933     switch (p_type) {
11934       case POINTER:
11935         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11936         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11937         break;
11938
11939         /*
11940            case FPOINTER:
11941            pic16_emitcode ("mov","b,a");
11942            pic16_emitcode("movx","a,@dptr");
11943            break;
11944
11945            case GPOINTER:
11946            pic16_emitcode ("push","b");
11947            pic16_emitcode ("push","acc");
11948            pic16_emitcode ("lcall","__gptrget");
11949            pic16_emitcode ("pop","b");
11950            break;
11951          */
11952       default:
11953         assert(0);
11954     }
11955     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11956     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11957     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11958     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11959     //        pic16_emitcode ("orl","a,b");
11960   }
11961
11962   //    if (p_type == GPOINTER)
11963   //        pic16_emitcode("pop","b");
11964
11965   switch (p_type) {
11966
11967     case POINTER:
11968       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11969       //        pic16_emitcode("mov","@%s,a",rname);
11970       break;
11971       /*
11972          case FPOINTER:
11973          pic16_emitcode("movx","@dptr,a");
11974          break;
11975
11976          case GPOINTER:
11977          DEBUGpic16_emitcode(";lcall","__gptrput");
11978          break;
11979        */
11980     default:
11981       assert(0);
11982   }
11983
11984   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11985 }
11986
11987 /*-----------------------------------------------------------------*/
11988 /* genDataPointerSet - remat pointer to data space                 */
11989 /*-----------------------------------------------------------------*/
11990 static void genDataPointerSet(operand *right,
11991                               operand *result,
11992                               iCode *ic)
11993 {
11994   int size, offset = 0, resoffset=0 ;
11995
11996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11997     pic16_aopOp(right,ic,FALSE);
11998
11999     size = AOP_SIZE(right);
12000
12001 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
12002
12003 #if 0
12004     if ( AOP_TYPE(result) == AOP_PCODE) {
12005       fprintf(stderr,"genDataPointerSet   %s, %d\n",
12006               AOP(result)->aopu.pcop->name,
12007                 (AOP(result)->aopu.pcop->type == PO_DIR)?
12008               PCOR(AOP(result)->aopu.pcop)->instance:
12009               PCOI(AOP(result)->aopu.pcop)->offset);
12010     }
12011 #endif
12012
12013     if(AOP(result)->aopu.pcop->type == PO_DIR)
12014       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
12015
12016     while (size--) {
12017       if (AOP_TYPE(right) == AOP_LIT) {
12018         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
12019         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
12020       } else {
12021         pic16_mov2w(AOP(right), offset);
12022         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
12023       }
12024       offset++;
12025       resoffset++;
12026     }
12027
12028     pic16_freeAsmop(right,NULL,ic,TRUE);
12029 }
12030
12031
12032
12033 /*-----------------------------------------------------------------*/
12034 /* genNearPointerSet - pic16_emitcode for near pointer put         */
12035 /*-----------------------------------------------------------------*/
12036 static void genNearPointerSet (operand *right,
12037                                operand *result,
12038                                iCode *ic)
12039 {
12040   asmop *aop = NULL;
12041   sym_link *retype;
12042   sym_link *ptype = operandType(result);
12043   sym_link *resetype;
12044
12045     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12046     retype= getSpec(operandType(right));
12047     resetype = getSpec(operandType(result));
12048
12049     pic16_aopOp(result,ic,FALSE);
12050
12051     /* if the result is rematerializable &
12052      * in data space & not a bit variable */
12053
12054     /* and result is not a bit variable */
12055     if (AOP_TYPE(result) == AOP_PCODE
12056 //      && AOP_TYPE(result) == AOP_IMMD
12057       && DCL_TYPE(ptype) == POINTER
12058       && !IS_BITFIELD(retype)
12059       && !IS_BITFIELD(resetype)) {
12060
12061         genDataPointerSet (right,result,ic);
12062         pic16_freeAsmop(result,NULL,ic,TRUE);
12063       return;
12064     }
12065
12066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12067     pic16_aopOp(right,ic,FALSE);
12068     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12069
12070     /* if bitfield then unpack the bits */
12071     if (IS_BITFIELD(resetype)) {
12072       genPackBits (resetype, result, right, NULL, POINTER);
12073     } else {
12074       /* we have can just get the values */
12075       int size = AOP_SIZE(right);
12076       int offset = 0 ;
12077
12078         pic16_loadFSR0(result, 0);
12079
12080         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12081         while (size--) {
12082           if (is_LitOp(right)) {
12083             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12084             if (size) {
12085               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12086             } else {
12087               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12088             }
12089           } else { // no literal
12090             if(size) {
12091               pic16_emitpcode(POC_MOVFF,
12092                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
12093                   pic16_popCopyReg(&pic16_pc_postinc0)));
12094             } else {
12095               pic16_emitpcode(POC_MOVFF,
12096                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
12097                   pic16_popCopyReg(&pic16_pc_indf0)));
12098             }
12099           }
12100
12101           offset++;
12102         }
12103     }
12104
12105     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12106     /* now some housekeeping stuff */
12107     if (aop) {
12108       /* we had to allocate for this iCode */
12109       pic16_freeAsmop(NULL,aop,ic,TRUE);
12110     } else {
12111       /* we did not allocate which means left
12112        * already in a pointer register, then
12113        * if size > 0 && this could be used again
12114        * we have to point it back to where it
12115        * belongs */
12116       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12117       if (AOP_SIZE(right) > 1
12118         && !OP_SYMBOL(result)->remat
12119         && ( OP_SYMBOL(result)->liveTo > ic->seq
12120         || ic->depth )) {
12121
12122           int size = AOP_SIZE(right) - 1;
12123
12124             while (size--)
12125               pic16_emitcode("decf","fsr0,f");
12126               //pic16_emitcode("dec","%s",rname);
12127       }
12128     }
12129
12130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12131     /* done */
12132 //release:
12133     pic16_freeAsmop(right,NULL,ic,TRUE);
12134     pic16_freeAsmop(result,NULL,ic,TRUE);
12135 }
12136
12137 /*-----------------------------------------------------------------*/
12138 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12139 /*-----------------------------------------------------------------*/
12140 static void genPagedPointerSet (operand *right,
12141                                operand *result,
12142                                iCode *ic)
12143 {
12144     asmop *aop = NULL;
12145     regs *preg = NULL ;
12146     char *rname , *l;
12147     sym_link *retype;
12148
12149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12150
12151     retype= getSpec(operandType(right));
12152
12153     pic16_aopOp(result,ic,FALSE);
12154
12155     /* if the value is already in a pointer register
12156        then don't need anything more */
12157     if (!AOP_INPREG(AOP(result))) {
12158         /* otherwise get a free pointer register */
12159         aop = newAsmop(0);
12160         preg = getFreePtr(ic,&aop,FALSE);
12161         pic16_emitcode("mov","%s,%s",
12162                 preg->name,
12163                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12164         rname = preg->name ;
12165     } else
12166         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12167
12168     pic16_freeAsmop(result,NULL,ic,TRUE);
12169     pic16_aopOp (right,ic,FALSE);
12170
12171     /* if bitfield then unpack the bits */
12172     if (IS_BITFIELD(retype))
12173         genPackBits (retype,result,right,rname,PPOINTER);
12174     else {
12175         /* we have can just get the values */
12176         int size = AOP_SIZE(right);
12177         int offset = 0 ;
12178
12179         while (size--) {
12180             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12181
12182             MOVA(l);
12183             pic16_emitcode("movx","@%s,a",rname);
12184
12185             if (size)
12186                 pic16_emitcode("inc","%s",rname);
12187
12188             offset++;
12189         }
12190     }
12191
12192     /* now some housekeeping stuff */
12193     if (aop) {
12194         /* we had to allocate for this iCode */
12195         pic16_freeAsmop(NULL,aop,ic,TRUE);
12196     } else {
12197         /* we did not allocate which means left
12198            already in a pointer register, then
12199            if size > 0 && this could be used again
12200            we have to point it back to where it
12201            belongs */
12202         if (AOP_SIZE(right) > 1 &&
12203             !OP_SYMBOL(result)->remat &&
12204             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12205               ic->depth )) {
12206             int size = AOP_SIZE(right) - 1;
12207             while (size--)
12208                 pic16_emitcode("dec","%s",rname);
12209         }
12210     }
12211
12212     /* done */
12213     pic16_freeAsmop(right,NULL,ic,TRUE);
12214
12215
12216 }
12217
12218 #if 0
12219 /* This code is not adjusted to PIC16 and fails utterly...
12220  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12221
12222 /*-----------------------------------------------------------------*/
12223 /* genFarPointerSet - set value from far space                     */
12224 /*-----------------------------------------------------------------*/
12225 static void genFarPointerSet (operand *right,
12226                               operand *result, iCode *ic)
12227 {
12228     int size, offset ;
12229     sym_link *retype = getSpec(operandType(right));
12230
12231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12232     pic16_aopOp(result,ic,FALSE);
12233
12234     /* if the operand is already in dptr
12235     then we do nothing else we move the value to dptr */
12236     if (AOP_TYPE(result) != AOP_STR) {
12237         /* if this is remateriazable */
12238         if (AOP_TYPE(result) == AOP_IMMD)
12239             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12240         else { /* we need to get it byte by byte */
12241             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12242             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12243             if (options.model == MODEL_FLAT24)
12244             {
12245                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12246             }
12247         }
12248     }
12249     /* so dptr know contains the address */
12250     pic16_freeAsmop(result,NULL,ic,TRUE);
12251     pic16_aopOp(right,ic,FALSE);
12252
12253     /* if bit then unpack */
12254     if (IS_BITFIELD(retype))
12255         genPackBits(retype,result,right,"dptr",FPOINTER);
12256     else {
12257         size = AOP_SIZE(right);
12258         offset = 0 ;
12259
12260         while (size--) {
12261             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12262             MOVA(l);
12263             pic16_emitcode("movx","@dptr,a");
12264             if (size)
12265                 pic16_emitcode("inc","dptr");
12266         }
12267     }
12268
12269     pic16_freeAsmop(right,NULL,ic,TRUE);
12270 }
12271 #endif
12272
12273 /*-----------------------------------------------------------------*/
12274 /* genGenPointerSet - set value from generic pointer space         */
12275 /*-----------------------------------------------------------------*/
12276 #if 0
12277 static void genGenPointerSet (operand *right,
12278                               operand *result, iCode *ic)
12279 {
12280         int i, size, offset, lit;
12281         sym_link *retype = getSpec(operandType(right));
12282
12283         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12284
12285         pic16_aopOp(result,ic,FALSE);
12286         pic16_aopOp(right,ic,FALSE);
12287         size = AOP_SIZE(right);
12288         offset = 0;
12289
12290         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12291
12292         /* if the operand is already in dptr
12293                 then we do nothing else we move the value to dptr */
12294         if (AOP_TYPE(result) != AOP_STR) {
12295                 /* if this is remateriazable */
12296                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12297                 // WARNING: anythig until "else" is untested!
12298                 if (AOP_TYPE(result) == AOP_IMMD) {
12299                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12300                         lit = (unsigned) ulFromVal (AOP(result)->aopu.aop_lit);
12301                         // load FSR0 from immediate
12302                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12303                         offset = 0;
12304                         while(size--) {
12305                                 if(size) {
12306                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12307                                 } else {
12308                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12309                                 }
12310                                 offset++;
12311                         }
12312                         goto release;
12313                 }
12314                 else { /* we need to get it byte by byte */
12315                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12316                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12317
12318                         // set up FSR0 with address of result
12319                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12320                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12321
12322                         /* hack hack! see if this the FSR. If so don't load W */
12323                         if(AOP_TYPE(right) != AOP_ACC) {
12324
12325                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12326
12327                                 if(AOP_TYPE(right) == AOP_LIT)
12328                                 {
12329                                         // copy literal
12330                                         // note: pic16_popGet handles sign extension
12331                                         for(i=0;i<size;i++) {
12332                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12333                                                 if(i < size-1)
12334                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12335                                                 else
12336                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12337                                         }
12338                                 } else {
12339                                         // copy regs
12340
12341                                         for(i=0;i<size;i++) {
12342                                                 if(i < size-1)
12343                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12344                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12345                                                 else
12346                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12347                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12348                                         }
12349                                 }
12350                                 goto release;
12351                         }
12352                         // right = ACC
12353                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12354                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12355                         goto release;
12356         } // if (AOP_TYPE(result) != AOP_IMMD)
12357
12358         } // if (AOP_TYPE(result) != AOP_STR)
12359         /* so dptr know contains the address */
12360
12361
12362         /* if bit then unpack */
12363         if (IS_BITFIELD(retype))
12364                 genPackBits(retype,result,right,"dptr",GPOINTER);
12365         else {
12366                 size = AOP_SIZE(right);
12367                 offset = 0 ;
12368
12369                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12370
12371                 // set up FSR0 with address of result
12372                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12373                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12374
12375                 while (size--) {
12376                         if (AOP_TYPE(right) == AOP_LIT) {
12377                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12378                                 if (size) {
12379                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12380                                 } else {
12381                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12382                                 }
12383                         } else { // no literal
12384                                 if(size) {
12385                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12386                                 } else {
12387                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12388                                 }
12389                         }
12390                         offset++;
12391                 }
12392         }
12393
12394         release:
12395         pic16_freeAsmop(right,NULL,ic,TRUE);
12396         pic16_freeAsmop(result,NULL,ic,TRUE);
12397 }
12398 #endif
12399
12400 static void genGenPointerSet (operand *right,
12401                               operand *result, iCode *ic)
12402 {
12403   int size;
12404   sym_link *retype = getSpec(operandType(result));
12405
12406     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12407
12408     pic16_aopOp(result,ic,FALSE);
12409     pic16_aopOp(right,ic,FALSE);
12410     size = AOP_SIZE(right);
12411
12412     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12413
12414
12415     /* if bit then unpack */
12416     if (IS_BITFIELD(retype)) {
12417 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12418       genPackBits(retype,result,right,"dptr",GPOINTER);
12419       goto release;
12420     }
12421
12422     size = AOP_SIZE(right);
12423
12424     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12425
12426
12427     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12428
12429     /* value of right+0 is placed on stack, which will be retrieved
12430      * by the support function thus restoring the stack. The important
12431      * thing is that there is no need to manually restore stack pointer
12432      * here */
12433     pushaop(AOP(right), 0);
12434 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12435     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12436     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12437     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12438
12439     /* load address to write to in WREG:FSR0H:FSR0L */
12440     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12441                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12442     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12443                                 pic16_popCopyReg(&pic16_pc_prodl)));
12444     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12445
12446     pic16_callGenericPointerRW(1, size);
12447
12448 release:
12449     pic16_freeAsmop(right,NULL,ic,TRUE);
12450     pic16_freeAsmop(result,NULL,ic,TRUE);
12451 }
12452
12453 /*-----------------------------------------------------------------*/
12454 /* genPointerSet - stores the value into a pointer location        */
12455 /*-----------------------------------------------------------------*/
12456 static void genPointerSet (iCode *ic)
12457 {
12458   operand *right, *result ;
12459   sym_link *type, *etype;
12460   int p_type;
12461
12462     FENTRY;
12463
12464     right = IC_RIGHT(ic);
12465     result = IC_RESULT(ic) ;
12466
12467     /* depending on the type of pointer we need to
12468     move it to the correct pointer register */
12469     type = operandType(result);
12470     etype = getSpec(type);
12471
12472     /* if left is of type of pointer then it is simple */
12473     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12474         p_type = DCL_TYPE(type);
12475     }
12476     else {
12477         /* we have to go by the storage class */
12478         p_type = PTR_TYPE(SPEC_OCLS(etype));
12479
12480 /*      if (SPEC_OCLS(etype)->codesp ) { */
12481 /*          p_type = CPOINTER ;  */
12482 /*      } */
12483 /*      else */
12484 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12485 /*              p_type = FPOINTER ; */
12486 /*          else */
12487 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12488 /*                  p_type = PPOINTER ; */
12489 /*              else */
12490 /*                  if (SPEC_OCLS(etype) == idata ) */
12491 /*                      p_type = IPOINTER ; */
12492 /*                  else */
12493 /*                      p_type = POINTER ; */
12494     }
12495
12496     /* now that we have the pointer type we assign
12497     the pointer values */
12498     switch (p_type) {
12499       case POINTER:
12500       case FPOINTER:
12501       case IPOINTER:
12502         genNearPointerSet (right,result,ic);
12503         break;
12504
12505       case PPOINTER:
12506         genPagedPointerSet (right,result,ic);
12507         break;
12508
12509 #if 0
12510       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12511       case FPOINTER:
12512         genFarPointerSet (right,result,ic);
12513         break;
12514 #endif
12515
12516       case GPOINTER:
12517         genGenPointerSet (right,result,ic);
12518         break;
12519
12520       default:
12521         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12522           "genPointerSet: illegal pointer type");
12523     }
12524 }
12525
12526 /*-----------------------------------------------------------------*/
12527 /* genIfx - generate code for Ifx statement                        */
12528 /*-----------------------------------------------------------------*/
12529 static void genIfx (iCode *ic, iCode *popIc)
12530 {
12531   operand *cond = IC_COND(ic);
12532   int isbit =0;
12533
12534     FENTRY;
12535
12536     pic16_aopOp(cond,ic,FALSE);
12537
12538     /* get the value into acc */
12539     if (AOP_TYPE(cond) != AOP_CRY)
12540       pic16_toBoolean(cond);
12541     else
12542       isbit = 1;
12543     /* the result is now in the accumulator */
12544     pic16_freeAsmop(cond,NULL,ic,TRUE);
12545
12546     /* if there was something to be popped then do it */
12547     if (popIc)
12548       genIpop(popIc);
12549
12550     /* if the condition is  a bit variable */
12551     if (isbit && IS_ITEMP(cond) &&
12552         SPIL_LOC(cond)) {
12553       genIfxJump(ic,"c");
12554       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12555     } else {
12556       if (isbit && !IS_ITEMP(cond))
12557         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12558         else
12559         genIfxJump(ic,"a");
12560     }
12561     ic->generated = 1;
12562 }
12563
12564 /*-----------------------------------------------------------------*/
12565 /* genAddrOf - generates code for address of                       */
12566 /*-----------------------------------------------------------------*/
12567 static void genAddrOf (iCode *ic)
12568 {
12569   operand *result, *left;
12570   int size;
12571   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12572   pCodeOp *pcop0, *pcop1, *pcop2;
12573
12574     FENTRY;
12575
12576     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12577
12578     sym = OP_SYMBOL( IC_LEFT(ic) );
12579
12580     if(sym->onStack) {
12581       /* get address of symbol on stack */
12582       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12583 #if 0
12584       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12585                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12586 #endif
12587
12588       // operands on stack are accessible via "FSR2 + index" with index
12589       // starting at 2 for arguments and growing from 0 downwards for
12590       // local variables (index == 0 is not assigned so we add one here)
12591       {
12592         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12593
12594           if (soffs <= 0) {
12595             assert (soffs < 0);
12596             soffs++;
12597           } // if
12598
12599           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12600           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12601           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12602           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12603           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12604           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12605           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12606       }
12607
12608       goto release;
12609     }
12610
12611 //      if(pic16_debug_verbose) {
12612 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12613 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12614 //      }
12615
12616     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12617     size = AOP_SIZE(IC_RESULT(ic));
12618
12619     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12620     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12621     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12622
12623     if (size == 3) {
12624       pic16_emitpcode(POC_MOVLW, pcop0);
12625       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12626       pic16_emitpcode(POC_MOVLW, pcop1);
12627       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12628       pic16_emitpcode(POC_MOVLW, pcop2);
12629       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12630     } else
12631     if (size == 2) {
12632       pic16_emitpcode(POC_MOVLW, pcop0);
12633       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12634       pic16_emitpcode(POC_MOVLW, pcop1);
12635     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12636     } else {
12637       pic16_emitpcode(POC_MOVLW, pcop0);
12638       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12639     }
12640
12641     pic16_freeAsmop(left, NULL, ic, FALSE);
12642 release:
12643     pic16_freeAsmop(result,NULL,ic,TRUE);
12644 }
12645
12646
12647 #if 0
12648 /*-----------------------------------------------------------------*/
12649 /* genFarFarAssign - assignment when both are in far space         */
12650 /*-----------------------------------------------------------------*/
12651 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12652 {
12653     int size = AOP_SIZE(right);
12654     int offset = 0;
12655     char *l ;
12656     /* first push the right side on to the stack */
12657     while (size--) {
12658         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12659         MOVA(l);
12660         pic16_emitcode ("push","acc");
12661     }
12662
12663     pic16_freeAsmop(right,NULL,ic,FALSE);
12664     /* now assign DPTR to result */
12665     pic16_aopOp(result,ic,FALSE);
12666     size = AOP_SIZE(result);
12667     while (size--) {
12668         pic16_emitcode ("pop","acc");
12669         pic16_aopPut(AOP(result),"a",--offset);
12670     }
12671     pic16_freeAsmop(result,NULL,ic,FALSE);
12672
12673 }
12674 #endif
12675
12676 /*-----------------------------------------------------------------*/
12677 /* genAssign - generate code for assignment                        */
12678 /*-----------------------------------------------------------------*/
12679 static void genAssign (iCode *ic)
12680 {
12681   operand *result, *right;
12682   sym_link *restype, *rtype;
12683   int size, offset,know_W;
12684   unsigned long lit = 0L;
12685
12686     result = IC_RESULT(ic);
12687     right  = IC_RIGHT(ic) ;
12688
12689     FENTRY;
12690
12691     /* if they are the same */
12692     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12693       return ;
12694
12695     /* reversed order operands are aopOp'ed so that result operand
12696      * is effective in case right is a stack symbol. This maneauver
12697      * allows to use the _G.resDirect flag later */
12698      pic16_aopOp(result,ic,TRUE);
12699     pic16_aopOp(right,ic,FALSE);
12700
12701     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12702
12703     /* if they are the same registers */
12704     if (pic16_sameRegs(AOP(right),AOP(result)))
12705       goto release;
12706
12707     /* if the result is a bit */
12708     if (AOP_TYPE(result) == AOP_CRY) {
12709       /* if the right size is a literal then
12710          we know what the value is */
12711       if (AOP_TYPE(right) == AOP_LIT) {
12712
12713         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12714             pic16_popGet(AOP(result),0));
12715
12716         if (((int) operandLitValue(right)))
12717           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12718               AOP(result)->aopu.aop_dir,
12719               AOP(result)->aopu.aop_dir);
12720         else
12721           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12722               AOP(result)->aopu.aop_dir,
12723               AOP(result)->aopu.aop_dir);
12724
12725         goto release;
12726       }
12727
12728       /* the right is also a bit variable */
12729       if (AOP_TYPE(right) == AOP_CRY) {
12730         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12731         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12732         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12733
12734         goto release ;
12735       }
12736
12737       /* we need to or */
12738       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12739       pic16_toBoolean(right);
12740       emitSKPZ;
12741       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12742       //pic16_aopPut(AOP(result),"a",0);
12743       goto release ;
12744     }
12745
12746     /* bit variables done */
12747     /* general case */
12748     size = AOP_SIZE(result);
12749     offset = 0 ;
12750
12751   /* bit variables done */
12752   /* general case */
12753   size = AOP_SIZE(result);
12754   restype = operandType(result);
12755   rtype = operandType(right);
12756   offset = 0 ;
12757
12758   if(AOP_TYPE(right) == AOP_LIT) {
12759     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12760     {
12761       lit = ulFromVal (AOP(right)->aopu.aop_lit);
12762
12763       /* patch tag for literals that are cast to pointers */
12764       if (IS_CODEPTR(restype)) {
12765         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12766         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12767       } else {
12768         if (IS_GENPTR(restype))
12769         {
12770           if (IS_CODEPTR(rtype)) {
12771             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12772             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12773           } else if (PIC_IS_DATA_PTR(rtype)) {
12774             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12775             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12776           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12777             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12778           } else if (IS_PTR(rtype)) {
12779             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12780             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12781           }
12782         }
12783       }
12784     } else {
12785       union {
12786         unsigned long lit_int;
12787         float lit_float;
12788       } info;
12789
12790
12791       if(IS_FIXED16X16(operandType(right))) {
12792         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12793       } else {
12794         /* take care if literal is a float */
12795         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12796         lit = info.lit_int;
12797       }
12798     }
12799   }
12800
12801 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12802 //                      sizeof(unsigned long int), sizeof(float));
12803
12804
12805     if (AOP_TYPE(right) == AOP_REG) {
12806       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12807       while (size--) {
12808         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12809       } // while
12810       goto release;
12811     }
12812
12813     /* when do we have to read the program memory?
12814      * - if right itself is a symbol in code space
12815      *   (we don't care what it points to if it's a pointer)
12816      * - AND right is not a function (we would want its address)
12817      */
12818     if(AOP_TYPE(right) != AOP_LIT
12819       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12820       && !IS_FUNC(OP_SYM_TYPE(right))
12821       && !IS_ITEMP(right)) {
12822
12823       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12824       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12825
12826       // set up table pointer
12827       if(is_LitOp(right)) {
12828 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12829         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12830         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12831         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12832         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12833         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12834         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12835       } else {
12836 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12837         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12838             pic16_popCopyReg(&pic16_pc_tblptrl)));
12839         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12840             pic16_popCopyReg(&pic16_pc_tblptrh)));
12841         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12842             pic16_popCopyReg(&pic16_pc_tblptru)));
12843       }
12844
12845       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12846       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12847       while(size--) {
12848         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12849         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12850             pic16_popGet(AOP(result),offset)));
12851         offset++;
12852       }
12853
12854       /* FIXME: for pointers we need to extend differently (according
12855        * to pointer type DATA/CODE/EEPROM/... :*/
12856       size = getSize(OP_SYM_TYPE(right));
12857       if(AOP_SIZE(result) > size) {
12858         size = AOP_SIZE(result) - size;
12859         while(size--) {
12860           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12861           offset++;
12862         }
12863       }
12864       goto release;
12865     }
12866
12867 #if 0
12868     /* VR - What is this?! */
12869     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12870       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12871
12872       if(aopIdx(AOP(result),0) == 4) {
12873         /* this is a workaround to save value of right into wreg too,
12874          * value of wreg is going to be used later */
12875         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12876         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12877         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12878         goto release;
12879       } else
12880 //      assert(0);
12881       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12882     }
12883 #endif
12884
12885     size = AOP_SIZE(right);
12886     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12887     know_W=-1;
12888     while (size--) {
12889       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12890       if(AOP_TYPE(right) == AOP_LIT) {
12891         if(lit&0xff) {
12892           if(know_W != (lit&0xff))
12893             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12894           know_W = lit&0xff;
12895           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12896         } else
12897           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12898
12899         lit >>= 8;
12900
12901       } else if (AOP_TYPE(right) == AOP_CRY) {
12902         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12903         if(offset == 0) {
12904           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12905           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12906           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12907         }
12908       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12909         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12910         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12911       } else {
12912         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12913
12914         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12915           if(AOP_TYPE(result) == AOP_ACC) {
12916             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12917           } else
12918             if(AOP_TYPE(right) == AOP_ACC) {
12919               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12920             } else {
12921               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12922             }
12923         }
12924       }
12925
12926       offset++;
12927     }
12928     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12929
12930 release:
12931   pic16_freeAsmop (right,NULL,ic,FALSE);
12932   pic16_freeAsmop (result,NULL,ic,TRUE);
12933 }
12934
12935 /*-----------------------------------------------------------------*/
12936 /* genJumpTab - generates code for jump table                       */
12937 /*-----------------------------------------------------------------*/
12938 static void genJumpTab (iCode *ic)
12939 {
12940   symbol *jtab;
12941   char *l;
12942   pCodeOp *jt_offs;
12943   pCodeOp *jt_offs_hi;
12944   pCodeOp *jt_label;
12945
12946     FENTRY;
12947
12948     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12949     /* get the condition into accumulator */
12950     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12951     MOVA(l);
12952     /* multiply by three */
12953     pic16_emitcode("add","a,acc");
12954     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12955
12956     jtab = newiTempLabel(NULL);
12957     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12958     pic16_emitcode("jmp","@a+dptr");
12959     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12960
12961 #if 0
12962     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12963     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12964     emitSKPNC;
12965     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12966     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12967     pic16_emitpLabel(jtab->key);
12968
12969 #else
12970
12971     jt_offs = pic16_popGetTempReg(0);
12972     jt_offs_hi = pic16_popGetTempReg(1);
12973     jt_label = pic16_popGetLabel (jtab->key);
12974     //fprintf (stderr, "Creating jump table...\n");
12975
12976     // calculate offset into jump table (idx * sizeof (GOTO))
12977     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12978     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12979     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12980     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12981     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12982     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12983     pic16_emitpcode(POC_MOVWF , jt_offs);
12984
12985     // prepare PCLATx (set to first entry in jump table)
12986     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12987     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12988     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12989     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12990     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12991
12992     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12993     pic16_emitpcode(POC_ADDWF , jt_offs);
12994     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12995     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12996     emitSKPNC;
12997     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12998
12999     // release temporaries and prepare jump into table (new PCL --> WREG)
13000     pic16_emitpcode(POC_MOVFW , jt_offs);
13001     pic16_popReleaseTempReg (jt_offs_hi, 1);
13002     pic16_popReleaseTempReg (jt_offs, 0);
13003
13004     // jump into the table
13005     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
13006
13007     pic16_emitpLabelFORCE(jtab->key);
13008 #endif
13009
13010     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
13011 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
13012
13013     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
13014     /* now generate the jump labels */
13015     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
13016          jtab = setNextItem(IC_JTLABELS(ic))) {
13017 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
13018         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
13019
13020     }
13021     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
13022
13023 }
13024
13025 /*-----------------------------------------------------------------*/
13026 /* genMixedOperation - gen code for operators between mixed types  */
13027 /*-----------------------------------------------------------------*/
13028 /*
13029   TSD - Written for the PIC port - but this unfortunately is buggy.
13030   This routine is good in that it is able to efficiently promote
13031   types to different (larger) sizes. Unfortunately, the temporary
13032   variables that are optimized out by this routine are sometimes
13033   used in other places. So until I know how to really parse the
13034   iCode tree, I'm going to not be using this routine :(.
13035 */
13036 static int genMixedOperation (iCode *ic)
13037 {
13038 #if 0
13039   operand *result = IC_RESULT(ic);
13040   sym_link *ctype = operandType(IC_LEFT(ic));
13041   operand *right = IC_RIGHT(ic);
13042   int ret = 0;
13043   int big,small;
13044   int offset;
13045
13046   iCode *nextic;
13047   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
13048
13049   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13050
13051   nextic = ic->next;
13052   if(!nextic)
13053     return 0;
13054
13055   nextright = IC_RIGHT(nextic);
13056   nextleft  = IC_LEFT(nextic);
13057   nextresult = IC_RESULT(nextic);
13058
13059   pic16_aopOp(right,ic,FALSE);
13060   pic16_aopOp(result,ic,FALSE);
13061   pic16_aopOp(nextright,  nextic, FALSE);
13062   pic16_aopOp(nextleft,   nextic, FALSE);
13063   pic16_aopOp(nextresult, nextic, FALSE);
13064
13065   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
13066
13067     operand *t = right;
13068     right = nextright;
13069     nextright = t;
13070
13071     pic16_emitcode(";remove right +","");
13072
13073   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
13074 /*
13075     operand *t = right;
13076     right = nextleft;
13077     nextleft = t;
13078 */
13079     pic16_emitcode(";remove left +","");
13080   } else
13081     return 0;
13082
13083   big = AOP_SIZE(nextleft);
13084   small = AOP_SIZE(nextright);
13085
13086   switch(nextic->op) {
13087
13088   case '+':
13089     pic16_emitcode(";optimize a +","");
13090     /* if unsigned or not an integral type */
13091     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
13092       pic16_emitcode(";add a bit to something","");
13093     } else {
13094
13095       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
13096
13097       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
13098         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
13099         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
13100       } else
13101         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13102
13103       offset = 0;
13104       while(--big) {
13105
13106         offset++;
13107
13108         if(--small) {
13109           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13110             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13111             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13112           }
13113
13114           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13115           emitSKPNC;
13116           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13117                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13118                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13119           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13120           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13121
13122         } else {
13123           pic16_emitcode("rlf","known_zero,w");
13124
13125           /*
13126             if right is signed
13127               btfsc  right,7
13128                addlw ff
13129           */
13130           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13131             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13132             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13133           } else {
13134             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13135           }
13136         }
13137       }
13138       ret = 1;
13139     }
13140   }
13141   ret = 1;
13142
13143 release:
13144   pic16_freeAsmop(right,NULL,ic,TRUE);
13145   pic16_freeAsmop(result,NULL,ic,TRUE);
13146   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13147   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13148   if(ret)
13149     nextic->generated = 1;
13150
13151   return ret;
13152 #else
13153   return 0;
13154 #endif
13155 }
13156 /*-----------------------------------------------------------------*/
13157 /* genCast - gen code for casting                                  */
13158 /*-----------------------------------------------------------------*/
13159 static void genCast (iCode *ic)
13160 {
13161   operand *result = IC_RESULT(ic);
13162   sym_link *ctype = operandType(IC_LEFT(ic));
13163   sym_link *rtype = operandType(IC_RIGHT(ic));
13164   sym_link *restype = operandType(IC_RESULT(ic));
13165   operand *right = IC_RIGHT(ic);
13166   int size, offset ;
13167
13168
13169     FENTRY;
13170
13171         /* if they are equivalent then do nothing */
13172 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13173 //              return ;
13174
13175         pic16_aopOp(result,ic,FALSE);
13176         pic16_aopOp(right,ic,FALSE) ;
13177
13178         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13179
13180
13181         /* if the result is a bit */
13182         if (AOP_TYPE(result) == AOP_CRY) {
13183
13184                 /* if the right size is a literal then
13185                  * we know what the value is */
13186                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13187
13188                 if (AOP_TYPE(right) == AOP_LIT) {
13189                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13190                                 pic16_popGet(AOP(result),0));
13191
13192                         if (((int) operandLitValue(right)))
13193                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13194                                         AOP(result)->aopu.aop_dir,
13195                                         AOP(result)->aopu.aop_dir);
13196                         else
13197                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13198                                         AOP(result)->aopu.aop_dir,
13199                                         AOP(result)->aopu.aop_dir);
13200                         goto release;
13201                 }
13202
13203                 /* the right is also a bit variable */
13204                 if (AOP_TYPE(right) == AOP_CRY) {
13205                         emitCLRC;
13206                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13207
13208                         pic16_emitcode("clrc","");
13209                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13210                                 AOP(right)->aopu.aop_dir,
13211                                 AOP(right)->aopu.aop_dir);
13212                         pic16_aopPut(AOP(result),"c",0);
13213                         goto release ;
13214                 }
13215
13216                 /* we need to or */
13217                 if (AOP_TYPE(right) == AOP_REG) {
13218                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13219                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13220                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13221                 }
13222                 pic16_toBoolean(right);
13223                 pic16_aopPut(AOP(result),"a",0);
13224                 goto release ;
13225         }
13226
13227         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13228           int offset = 1;
13229
13230                 size = AOP_SIZE(result);
13231
13232                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13233
13234                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13235                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13236                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13237
13238                 while (size--)
13239                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13240
13241                 goto release;
13242         }
13243
13244         if(IS_BITFIELD(getSpec(restype))
13245           && IS_BITFIELD(getSpec(rtype))) {
13246           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13247         }
13248
13249         /* port from pic14 to cope with generic pointers */
13250         if (PIC_IS_TAGGED(restype))
13251         {
13252           operand *result = IC_RESULT(ic);
13253           //operand *left = IC_LEFT(ic);
13254           operand *right = IC_RIGHT(ic);
13255           int tag = 0xff;
13256
13257           /* copy common part */
13258           int max, size = AOP_SIZE(result);
13259           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13260           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13261
13262           max = size;
13263           while (size--)
13264           {
13265             pic16_mov2w (AOP(right), size);
13266             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13267           } // while
13268
13269           /* upcast into generic pointer type? */
13270           if (IS_GENPTR(restype)
13271               && !PIC_IS_TAGGED(rtype)
13272               && (AOP_SIZE(result) > max))
13273           {
13274             /* determine appropriate tag for right */
13275             if (PIC_IS_DATA_PTR(rtype))
13276               tag = GPTR_TAG_DATA;
13277             else if (IS_CODEPTR(rtype))
13278               tag = GPTR_TAG_CODE;
13279             else if (PIC_IS_DATA_PTR(ctype)) {
13280               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13281               tag = GPTR_TAG_DATA;
13282             } else if (IS_CODEPTR(ctype)) {
13283               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13284               tag = GPTR_TAG_CODE;
13285             } else if (IS_PTR(rtype)) {
13286               PERFORM_ONCE(weirdcast,
13287               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13288               );
13289               tag = GPTR_TAG_DATA;
13290             } else {
13291               PERFORM_ONCE(weirdcast,
13292               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13293               );
13294               tag = GPTR_TAG_DATA;
13295             }
13296
13297             assert (AOP_SIZE(result) == 3);
13298             /* zero-extend address... */
13299             for (size = max; size < AOP_SIZE(result)-1; size++)
13300               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13301             /* ...and add tag */
13302             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13303           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13304             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13305             for (size = max; size < AOP_SIZE(result)-1; size++)
13306               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13307             /* add __code tag */
13308             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13309           } else if (AOP_SIZE(result) > max) {
13310             /* extend non-pointers */
13311             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13312             pic16_addSign(result, max, 0);
13313           } // if
13314           goto release;
13315         }
13316
13317         /* if they are the same size : or less */
13318         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13319
13320                 /* if they are in the same place */
13321                 if (pic16_sameRegs(AOP(right),AOP(result)))
13322                         goto release;
13323
13324                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13325 #if 0
13326                 if (IS_PTR_CONST(rtype))
13327 #else
13328                 if (IS_CODEPTR(rtype))
13329 #endif
13330                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13331
13332 #if 0
13333                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13334 #else
13335                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13336 #endif
13337                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13338
13339 #if 0
13340                 if(AOP_TYPE(right) == AOP_IMMD) {
13341                   pCodeOp *pcop0, *pcop1, *pcop2;
13342                   symbol *sym = OP_SYMBOL( right );
13343
13344                         size = AOP_SIZE(result);
13345                         /* low */
13346                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13347                         /* high */
13348                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13349                         /* upper */
13350                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13351
13352                         if (size == 3) {
13353                                 pic16_emitpcode(POC_MOVLW, pcop0);
13354                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13355                                 pic16_emitpcode(POC_MOVLW, pcop1);
13356                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13357                                 pic16_emitpcode(POC_MOVLW, pcop2);
13358                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13359                         } else
13360                         if (size == 2) {
13361                                 pic16_emitpcode(POC_MOVLW, pcop0);
13362                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13363                                 pic16_emitpcode(POC_MOVLW, pcop1);
13364                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13365                         } else {
13366                                 pic16_emitpcode(POC_MOVLW, pcop0);
13367                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13368                         }
13369                 } else
13370 #endif
13371                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13372                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13373                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13374
13375                         if(AOP_SIZE(result) < 2) {
13376                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13377                         } else {
13378                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13379                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13380                         }
13381                 } else {
13382                         /* if they in different places then copy */
13383                         size = AOP_SIZE(result);
13384                         offset = 0 ;
13385                         while (size--) {
13386                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13387                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13388                                 offset++;
13389                         }
13390                 }
13391                 goto release;
13392         }
13393
13394         /* if the result is of type pointer */
13395         if (IS_PTR(ctype)) {
13396           int p_type;
13397           sym_link *type = operandType(right);
13398           sym_link *etype = getSpec(type);
13399
13400                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13401
13402                 /* pointer to generic pointer */
13403                 if (IS_GENPTR(ctype)) {
13404                   char *l = zero;
13405
13406                         if (IS_PTR(type))
13407                                 p_type = DCL_TYPE(type);
13408                         else {
13409                 /* we have to go by the storage class */
13410                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13411
13412 /*              if (SPEC_OCLS(etype)->codesp )  */
13413 /*                  p_type = CPOINTER ;  */
13414 /*              else */
13415 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13416 /*                      p_type = FPOINTER ; */
13417 /*                  else */
13418 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13419 /*                          p_type = PPOINTER; */
13420 /*                      else */
13421 /*                          if (SPEC_OCLS(etype) == idata ) */
13422 /*                              p_type = IPOINTER ; */
13423 /*                          else */
13424 /*                              p_type = POINTER ; */
13425             }
13426
13427             /* the first two bytes are known */
13428       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13429             size = GPTRSIZE - 1;
13430             offset = 0 ;
13431             while (size--) {
13432               if(offset < AOP_SIZE(right)) {
13433                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13434                 pic16_mov2f(AOP(result), AOP(right), offset);
13435 /*
13436                 if ((AOP_TYPE(right) == AOP_PCODE) &&
13437                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13438                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13439                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13440                 } else {
13441
13442                   pic16_aopPut(AOP(result),
13443                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13444                          offset);
13445                 }
13446 */
13447               } else
13448                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13449               offset++;
13450             }
13451             /* the last byte depending on type */
13452             switch (p_type) {
13453             case IPOINTER:
13454             case POINTER:
13455             case FPOINTER:
13456                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13457                 break;
13458
13459             case CPOINTER:
13460                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13461                 break;
13462
13463             case PPOINTER:
13464               pic16_emitcode(";BUG!? ","%d",__LINE__);
13465                 l = "#0x03";
13466                 break;
13467
13468             case GPOINTER:
13469                 if (GPTRSIZE > AOP_SIZE(right)) {
13470                   // assume __data pointer... THIS MIGHT BE WRONG!
13471                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13472                 } else {
13473                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13474                 }
13475               break;
13476
13477             default:
13478                 /* this should never happen */
13479                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13480                        "got unknown pointer type");
13481                 exit(1);
13482             }
13483             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
13484             goto release ;
13485         }
13486
13487
13488         assert( 0 );
13489         /* just copy the pointers */
13490         size = AOP_SIZE(result);
13491         offset = 0 ;
13492         while (size--) {
13493             pic16_aopPut(AOP(result),
13494                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13495                    offset);
13496             offset++;
13497         }
13498         goto release ;
13499     }
13500
13501
13502
13503     /* so we now know that the size of destination is greater
13504     than the size of the source.
13505     Now, if the next iCode is an operator then we might be
13506     able to optimize the operation without performing a cast.
13507     */
13508     if(genMixedOperation(ic))
13509       goto release;
13510
13511     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13512
13513     /* we move to result for the size of source */
13514     size = AOP_SIZE(right);
13515     offset = 0 ;
13516
13517     while (size--) {
13518       if(!_G.resDirect)
13519         pic16_mov2f(AOP(result), AOP(right), offset);
13520       offset++;
13521     }
13522
13523     /* now depending on the sign of the destination */
13524     size = AOP_SIZE(result) - AOP_SIZE(right);
13525     /* if unsigned or not an integral type */
13526     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13527       while (size--)
13528         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13529     } else {
13530       /* we need to extend the sign :( */
13531
13532       if(size == 1) {
13533         /* Save one instruction of casting char to int */
13534         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13535         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13536         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13537       } else {
13538         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13539
13540         if(offset)
13541           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13542         else
13543           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13544
13545         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13546
13547         while (size--)
13548           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13549       }
13550     }
13551
13552 release:
13553     pic16_freeAsmop(right,NULL,ic,TRUE);
13554     pic16_freeAsmop(result,NULL,ic,TRUE);
13555
13556 }
13557
13558 /*-----------------------------------------------------------------*/
13559 /* genDjnz - generate decrement & jump if not zero instrucion      */
13560 /*-----------------------------------------------------------------*/
13561 static int genDjnz (iCode *ic, iCode *ifx)
13562 {
13563     symbol *lbl, *lbl1;
13564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13565
13566     if (!ifx)
13567         return 0;
13568
13569     /* if the if condition has a false label
13570        then we cannot save */
13571     if (IC_FALSE(ifx))
13572         return 0;
13573
13574     /* if the minus is not of the form
13575        a = a - 1 */
13576     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13577         !IS_OP_LITERAL(IC_RIGHT(ic)))
13578         return 0;
13579
13580     if (operandLitValue(IC_RIGHT(ic)) != 1)
13581         return 0;
13582
13583     /* if the size of this greater than one then no
13584        saving */
13585     if (getSize(operandType(IC_RESULT(ic))) > 1)
13586         return 0;
13587
13588     /* otherwise we can save BIG */
13589     lbl = newiTempLabel(NULL);
13590     lbl1= newiTempLabel(NULL);
13591
13592     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13593
13594     if (IS_AOP_PREG(IC_RESULT(ic))) {
13595         pic16_emitcode("dec","%s",
13596                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13597         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13598         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13599     } else {
13600
13601
13602       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13603       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13604
13605       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13606       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13607
13608     }
13609
13610     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13611     ifx->generated = 1;
13612     return 1;
13613 }
13614
13615 /*-----------------------------------------------------------------*/
13616 /* genReceive - generate code for a receive iCode                  */
13617 /*-----------------------------------------------------------------*/
13618 static void genReceive (iCode *ic)
13619 {
13620
13621   FENTRY;
13622
13623 #if 0
13624   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13625         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13626 #endif
13627 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13628
13629   if (isOperandInFarSpace(IC_RESULT(ic))
13630       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13631           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13632
13633     int size = getSize(operandType(IC_RESULT(ic)));
13634     int offset =  pic16_fReturnSizePic - size;
13635
13636       assert( 0 );
13637       while (size--) {
13638         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13639                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13640                       offset++;
13641         }
13642
13643       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13644
13645       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13646       size = AOP_SIZE(IC_RESULT(ic));
13647       offset = 0;
13648       while (size--) {
13649         pic16_emitcode ("pop","acc");
13650         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13651       }
13652   } else {
13653     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13654     _G.accInUse++;
13655     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13656     _G.accInUse--;
13657
13658     /* set pseudo stack pointer to where it should be - dw*/
13659     GpsuedoStkPtr = ic->parmBytes;
13660
13661     /* setting GpsuedoStkPtr has side effects here: */
13662     /* FIXME: What's the correct size of the return(ed) value?
13663      *        For now, assuming '4' as before... */
13664     assignResultValue(IC_RESULT(ic), 4, 0);
13665   }
13666
13667   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13668 }
13669
13670 /*-----------------------------------------------------------------*/
13671 /* genDummyRead - generate code for dummy read of volatiles        */
13672 /*-----------------------------------------------------------------*/
13673 static void
13674 genDummyRead (iCode * ic)
13675 {
13676   operand *op;
13677   int i;
13678
13679   op = IC_RIGHT(ic);
13680   if (op && IS_SYMOP(op)) {
13681     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13682       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13683       return;
13684     }
13685     pic16_aopOp (op, ic, FALSE);
13686     for (i=0; i < AOP_SIZE(op); i++) {
13687       // may need to protect this from the peepholer -- this is not nice but works...
13688       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13689       pic16_mov2w (AOP(op),i);
13690       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13691     } // for i
13692     pic16_freeAsmop (op, NULL, ic, TRUE);
13693   } else if (op) {
13694     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13695   } // if
13696 }
13697
13698 /*-----------------------------------------------------------------*/
13699 /* genpic16Code - generate code for pic16 based controllers        */
13700 /*-----------------------------------------------------------------*/
13701 /*
13702  * At this point, ralloc.c has gone through the iCode and attempted
13703  * to optimize in a way suitable for a PIC. Now we've got to generate
13704  * PIC instructions that correspond to the iCode.
13705  *
13706  * Once the instructions are generated, we'll pass through both the
13707  * peep hole optimizer and the pCode optimizer.
13708  *-----------------------------------------------------------------*/
13709
13710 void genpic16Code (iCode *lic)
13711 {
13712   iCode *ic;
13713   int cln = 0;
13714
13715     lineHead = lineCurr = NULL;
13716
13717     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13718     pic16_addpBlock(pb);
13719
13720 #if 0
13721     /* if debug information required */
13722     if (options.debug && currFunc) {
13723       if (currFunc) {
13724         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13725       }
13726     }
13727 #endif
13728
13729     for (ic = lic ; ic ; ic = ic->next ) {
13730
13731       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13732       if ( cln != ic->lineno ) {
13733         if ( options.debug ) {
13734           debugFile->writeCLine (ic);
13735         }
13736
13737         if(!options.noCcodeInAsm) {
13738           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
13739               printCLine(ic->filename, ic->lineno)));
13740         }
13741
13742         cln = ic->lineno ;
13743       }
13744
13745       if(options.iCodeInAsm) {
13746         const char *iLine;
13747
13748         /* insert here code to print iCode as comment */
13749         iLine = printILine(ic);
13750         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13751         dbuf_free(iLine);
13752       }
13753
13754       /* if the result is marked as
13755        * spilt and rematerializable or code for
13756        * this has already been generated then
13757        * do nothing */
13758       if (resultRemat(ic) || ic->generated )
13759         continue ;
13760
13761       /* depending on the operation */
13762       switch (ic->op) {
13763         case '!' :
13764           pic16_genNot(ic);
13765           break;
13766
13767         case '~' :
13768           pic16_genCpl(ic);
13769           break;
13770
13771         case UNARYMINUS:
13772           genUminus (ic);
13773           break;
13774
13775         case IPUSH:
13776           genIpush (ic);
13777           break;
13778
13779         case IPOP:
13780           /* IPOP happens only when trying to restore a
13781            * spilt live range, if there is an ifx statement
13782            * following this pop then the if statement might
13783            * be using some of the registers being popped which
13784            * would destroy the contents of the register so
13785            * we need to check for this condition and handle it */
13786            if (ic->next
13787              && ic->next->op == IFX
13788              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
13789                genIfx (ic->next,ic);
13790           else
13791             genIpop (ic);
13792           break;
13793
13794         case CALL:
13795           genCall (ic);
13796           break;
13797
13798         case PCALL:
13799           genPcall (ic);
13800           break;
13801
13802         case FUNCTION:
13803           genFunction (ic);
13804           break;
13805
13806         case ENDFUNCTION:
13807           genEndFunction (ic);
13808           break;
13809
13810         case RETURN:
13811           genRet (ic);
13812           break;
13813
13814         case LABEL:
13815           genLabel (ic);
13816           break;
13817
13818         case GOTO:
13819           genGoto (ic);
13820           break;
13821
13822         case '+' :
13823           pic16_genPlus (ic) ;
13824           break;
13825
13826         case '-' :
13827           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13828             pic16_genMinus (ic);
13829           break;
13830
13831         case '*' :
13832           genMult (ic);
13833           break;
13834
13835         case '/' :
13836           genDiv (ic) ;
13837           break;
13838
13839         case '%' :
13840           genMod (ic);
13841           break;
13842
13843         case '>' :
13844           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
13845           break;
13846
13847         case '<' :
13848           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13849           break;
13850
13851         case LE_OP:
13852         case GE_OP:
13853         case NE_OP:
13854           /* note these two are xlated by algebraic equivalence
13855            * during parsing SDCC.y */
13856           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13857             "got '>=' or '<=' shouldn't have come here");
13858           break;
13859
13860         case EQ_OP:
13861           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13862           break;
13863
13864         case AND_OP:
13865           genAndOp (ic);
13866           break;
13867
13868         case OR_OP:
13869           genOrOp (ic);
13870           break;
13871
13872         case '^' :
13873           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13874           break;
13875
13876         case '|' :
13877           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13878           break;
13879
13880         case BITWISEAND:
13881           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13882           break;
13883
13884         case INLINEASM:
13885           genInline (ic);
13886           break;
13887
13888         case RRC:
13889           genRRC (ic);
13890           break;
13891
13892         case RLC:
13893           genRLC (ic);
13894           break;
13895
13896         case GETHBIT:
13897           genGetHbit (ic);
13898           break;
13899
13900         case LEFT_OP:
13901           genLeftShift (ic);
13902           break;
13903
13904         case RIGHT_OP:
13905           genRightShift (ic);
13906           break;
13907
13908         case GET_VALUE_AT_ADDRESS:
13909           genPointerGet(ic);
13910           break;
13911
13912         case '=' :
13913           if (POINTER_SET(ic))
13914             genPointerSet(ic);
13915           else
13916             genAssign(ic);
13917           break;
13918
13919         case IFX:
13920           genIfx (ic,NULL);
13921           break;
13922
13923         case ADDRESS_OF:
13924           genAddrOf (ic);
13925           break;
13926
13927         case JUMPTABLE:
13928           genJumpTab (ic);
13929           break;
13930
13931         case CAST:
13932           genCast (ic);
13933           break;
13934
13935         case RECEIVE:
13936           genReceive(ic);
13937           break;
13938
13939         case SEND:
13940           addSet(&_G.sendSet,ic);
13941           break;
13942
13943         case DUMMY_READ_VOLATILE:
13944           genDummyRead (ic);
13945           break;
13946
13947         default :
13948           ic = ic;
13949       }
13950     }
13951
13952
13953     /* now we are ready to call the
13954        peep hole optimizer */
13955     if (!options.nopeep)
13956       peepHole (&lineHead);
13957
13958     /* now do the actual printing */
13959     printLine (lineHead, codeOutBuf);
13960
13961 #ifdef PCODE_DEBUG
13962     DFPRINTF((stderr,"printing pBlock\n\n"));
13963     pic16_printpBlock(stdout,pb);
13964 #endif
13965
13966     return;
13967 }